package com.ims.core.doc.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import com.baiwang.open.entity.ErrorResponse;
import com.baiwang.open.entity.response.*;
import com.baiwang.open.entity.response.node.*;
import com.ims.common.annotation.RequestParamsSplit;
import com.ims.common.core.domain.model.LoginUser;
import com.ims.common.exception.ServiceException;
import com.ims.common.exception.base.BaseException;
import com.ims.common.utils.DateUtils;
import com.ims.common.utils.DictUtils;
import com.ims.common.utils.SecurityUtils;
import com.ims.common.utils.uuid.IdUtils;
import com.ims.core.doc.domain.*;
import com.ims.core.doc.service.ITInDeductionApplyService;
import com.ims.core.doc.service.ITInInvoice51Service;
import com.ims.core.doc.service.ITInInvoice61Service;
import com.ims.core.doc.vo.bwapi.DeductionApplyInvoice;
import com.ims.core.doc.vo.bwapi.DeductionApplyorCancelnon;
import com.ims.core.doc.vo.bwapi.InvoiceForValidate;
import com.ims.core.enums.*;
import com.ims.manager.ImsAsyncManager;
import com.ims.manager.factory.ImsAsyncFactory;
import com.ims.system.domain.TSysSite;
import com.ims.system.service.ITSysSiteService;
import com.ims.util.BaiwangUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Objects;

import com.ims.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.ims.core.doc.mapper.TInInvoiceMapper;
import com.ims.core.doc.service.ITInInvoiceService;
import org.springframework.util.CollectionUtils;

/**
 * 进项发票Service业务层处理
 *
 * @author IMS
 * @date 2024-05-20
 */
@Service
public class TInInvoiceServiceImpl implements ITInInvoiceService
{
    //日志
    private static final Logger logger = LoggerFactory.getLogger(TInInvoiceServiceImpl.class);

    @Autowired
    private ITInInvoice51Service tInInvoice51Service;

    @Autowired
    private ITInInvoice61Service tInInvoice61Service;

    @Autowired
    private TInInvoiceMapper tInInvoiceMapper;

    @Autowired
    private ITSysSiteService tSysSiteService;

    @Autowired
    private ITInDeductionApplyService tInDeductionApplyService;

    /**
     * 查询进项发票
     *
     * @param invoiceId 进项发票主键
     * @return 进项发票
     */
    @Override
    public TInInvoice selectTInInvoiceByInvoiceId(String invoiceId)
    {
        return tInInvoiceMapper.selectTInInvoiceByInvoiceId(invoiceId);
    }

    /**
     * 查询进项发票
     *
     * @param invoiceNumber 进项发票发票号
     * @return 进项发票
     */
    @Override
    public TInInvoice selectTInInvoiceByInvoiceNumber(String invoiceNumber)
    {
        TInInvoice inInvoiceCondition = new TInInvoice();
        inInvoiceCondition.setInvoiceNo(invoiceNumber);
        List<TInInvoice> inInvoiceList = selectTInInvoiceList(inInvoiceCondition);
        if(CollectionUtils.isEmpty(inInvoiceList)){
            return null;
        }
        return inInvoiceList.get(0);
    }

    /**
     * 查询进项发票列表
     *
     * @param tInInvoice 进项发票
     * @return 进项发票
     */
    @Override
    @RequestParamsSplit
    public List<TInInvoice> selectTInInvoiceList(TInInvoice tInInvoice)
    {
        return tInInvoiceMapper.selectTInInvoiceList(tInInvoice);
    }

    @Override
    @RequestParamsSplit
    public List<TInInvoice> selectDeductionInInvoiceList(TInInvoice tInInvoice) {
        tInInvoice.setIsInvoicedataSync("1");
        return tInInvoiceMapper.selectTInInvoiceList(tInInvoice);
    }

    @Override
    public List<TInInvoice> selectDeductionInInvoiceListByPeriod(String period) {
        TInInvoice inInvoiceCondition = new TInInvoice();
        inInvoiceCondition.setDeductiblePeriod(period);
        // 已通过
        inInvoiceCondition.setDeductible(Deductible.REN_ZHENG_TONG_GUO.getCode());
        return tInInvoiceMapper.selectTInInvoiceList(inInvoiceCondition);
    }

    /**
     * 新增进项发票
     *
     * @param tInInvoice 进项发票
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertTInInvoice(TInInvoice tInInvoice)
    {
        tInInvoice.setInvoiceId(IdUtils.simpleUUID());
        tInInvoice.setCreateTime(DateUtils.getNowDate());
        int rows = tInInvoiceMapper.insertTInInvoice(tInInvoice);
        insertTInInvoiceEntry(tInInvoice);
        return rows;
    }

    /**
     * 修改进项发票
     *
     * @param tInInvoice 进项发票
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateTInInvoice(TInInvoice tInInvoice)
    {
        tInInvoice.setUpdateTime(DateUtils.getNowDate());
        tInInvoiceMapper.deleteTInInvoiceEntryByInvoiceId(tInInvoice.getInvoiceId());
        insertTInInvoiceEntry(tInInvoice);
        return tInInvoiceMapper.updateTInInvoice(tInInvoice);
    }

    /**
     * 批量删除进项发票
     *
     * @param invoiceIds 需要删除的进项发票主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteTInInvoiceByInvoiceIds(String[] invoiceIds)
    {
        tInInvoiceMapper.deleteTInInvoiceEntryByInvoiceIds(invoiceIds);
        return tInInvoiceMapper.deleteTInInvoiceByInvoiceIds(invoiceIds);
    }


    /**
     * 删除进项发票信息
     *
     * @param invoiceId 进项发票主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteTInInvoiceByInvoiceId(String invoiceId)
    {
        tInInvoiceMapper.deleteTInInvoiceEntryByInvoiceId(invoiceId);
        return tInInvoiceMapper.deleteTInInvoiceByInvoiceId(invoiceId);
    }

    /**
     * 新增进项明细项信息
     *
     * @param tInInvoice 进项发票对象
     */
    public void insertTInInvoiceEntry(TInInvoice tInInvoice)
    {
        List<TInInvoiceEntry> tInInvoiceEntryList = tInInvoice.getTInInvoiceEntryList();
        String invoiceId = tInInvoice.getInvoiceId();
        if (StringUtils.isNotNull(tInInvoiceEntryList))
        {
            List<TInInvoiceEntry> list = new ArrayList<TInInvoiceEntry>();
            for (TInInvoiceEntry tInInvoiceEntry : tInInvoiceEntryList)
            {
                tInInvoiceEntry.setEntryId(IdUtils.simpleUUID());
                tInInvoiceEntry.setInvoiceId(invoiceId);
                list.add(tInInvoiceEntry);
            }
            if (list.size() > 0)
            {
                tInInvoiceMapper.batchTInInvoiceEntry(list);
            }
        }
    }

    /**
     * 从百望）同步历史发票信息
     */
    @Override
    public void invoiceHistoryDataSyncFromBaiwang() {
        // 查询符合条件的进项发票
        TInInvoice tInInvoiceCondition = new TInInvoice();
        List<TInInvoice> inInvoiceList = selectTInInvoiceList(tInInvoiceCondition);
        //
        for(TInInvoice tInInvoice : inInvoiceList){
            // 进项发票的完整信息应通过查验接口获取
            InvoiceForValidate invoiceForValidate = new InvoiceForValidate();
            // 20位 发票号码
            invoiceForValidate.setInvoiceNumber(tInInvoice.getInvoiceNo());
            // 发票代码位数为10位或12位
            invoiceForValidate.setInvoiceCode(tInInvoice.getInvoiceCode());
            invoiceForValidate.setCheckCode(tInInvoice.getCheckCode());
            // 购方税号
            invoiceForValidate.setTaxNo(tInInvoice.getPurchaserTaxNo());
            //
            invoiceForValidate.setBillingDate(tInInvoice.getInvoiceDate());
            invoiceForValidate.setTotalAmount(tInInvoice.getTotalAmount().toString());
            invoiceForValidate.setInvoiceType(tInInvoice.getInvoiceType());
            try {
                InputComplianceValidateResponse response = BaiwangUtils.validate(invoiceForValidate);
                if(!response.getSuccess()){
                    logger.error("发票 {} 查验失败 {}, {}", tInInvoice.getInvoiceNo(), response.getErrorResponse().getCode(), response.getErrorResponse().getMessage());
                } else {
                    // 解析返回
                    InputComplianceValidate inputComplianceValidate = response.getResponse();
                    // 发票类型 即查验接口不返回非增值税发票
                    // 01:增值税专用发票
                    // 03:机动车销售统一发票
                    // 04:增值税普通发票
                    // 08:增值税电子专用发票
                    // 10:增值税电子普通发票
                    // 11:增值税普通发票(卷式)
                    // 14: 道路通行费电子普通发票
                    // 15:二手车销售统一发票
                    // 31:数电票（增值税专用发票）
                    // 32:数电票（普通发票）
                    // 51: 数电票（铁路电子客票）
                    // 61:数电票（航空运输电子客票行程单）
                    // 85 :数电纸质发票（增值税专用发票）
                    // 86:数电纸质发票（普通发票）
                    String invoiceType = inputComplianceValidate.getInvoiceType();
                    // 发票数据
                    InputComplianceValidateFullInvoiceInfo inputComplianceValidateFullInvoiceInfo = inputComplianceValidate.getData();

                    // 购方名称
                    tInInvoice.setPurchaserName(inputComplianceValidateFullInvoiceInfo.getPurchaserName());
                    // 购方开户行账户
                    tInInvoice.setPurchaserBank(inputComplianceValidateFullInvoiceInfo.getPurchaserBank());
                    // 所属行政区名称
                    tInInvoice.setAdministrativeDivisionName(inputComplianceValidateFullInvoiceInfo.getAdministrativeDivisionName());
                    // 机器编号
                    tInInvoice.setMachineCode(inputComplianceValidateFullInvoiceInfo.getMachineCode());
                    // 收货人
                    tInInvoice.setReceivingClerk(inputComplianceValidateFullInvoiceInfo.getReceivingClerk());
                    // 成品油标记
                    tInInvoice.setOilMark(inputComplianceValidateFullInvoiceInfo.getOilMark());
                    // 校验码
                    tInInvoice.setCheckCode(inputComplianceValidateFullInvoiceInfo.getCheckCode());
                    // 销方地址电话
                    tInInvoice.setSalesAddressPhone(inputComplianceValidateFullInvoiceInfo.getSalesAddressPhone());
                    // 销方开户行
                    tInInvoice.setSalesBank(inputComplianceValidateFullInvoiceInfo.getSalesBank());
                    // 销方开户行账户
                    tInInvoice.setSalesBankNo(inputComplianceValidateFullInvoiceInfo.getSalesBankNo());
                    // 数电发票号码
                    tInInvoice.setEInvoiceNumber(inputComplianceValidateFullInvoiceInfo.getEInvoiceNumber());
                    // 购方地址电话
                    tInInvoice.setPurchaserAddressPhone(inputComplianceValidateFullInvoiceInfo.getPurchaserAddressPhone());
                    // 发票状态
                    tInInvoice.setInvoiceState(inputComplianceValidateFullInvoiceInfo.getState());
                    tInInvoice.setInvoiceStateName(DictUtils.getDictLabel("in_invoice_type", inputComplianceValidateFullInvoiceInfo.getState()));
                    // t_in_invoice 对象保存
                    // FIXME 初始的报销状态？
//                    tInInvoice.setSubmitStatus(SubmitStatus.NOT_REIMBURSED.getCode());
//                    tInInvoice.setSubmitStatusName(SubmitStatus.NOT_REIMBURSED.getName());
                    // 发票备注
                    tInInvoice.setInvoiceRemark(inputComplianceValidateFullInvoiceInfo.getRemarks());
                    // 是否红票
                    // tInInvoice.setIsRed(IsRed.BLUE.getCode());
                    // 入账状态
//                    tInInvoice.setAccountStatus(AccountStatus.NOT_ACCOUNTED.getCode());
//                    tInInvoice.setAccountStatusName(AccountStatus.NOT_ACCOUNTED.getName());
                    // 处理状态
                    tInInvoice.setProcessStatus(ProcessStatus.INVOICED.getCode());
                    tInInvoice.setProcessStatusName(ProcessStatus.INVOICED.getName());

                    // 签收状态
//                    tInInvoice.setSignStatus(SignStatus.SIGNED.getCode());
//                    tInInvoice.setSignStatusName(SignStatus.SIGNED.getName());

                    // 明细
                    // 51:数电票（铁路电子客票）
                    TInInvoice51 tInInvoice51 = new TInInvoice51();
                    if(invoiceType.equals(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode())){
                        BeanUtils.copyProperties(tInInvoice, tInInvoice51);
                        // FIXME 字段对应需要重新检查，需要手动指定字段赋值
                        BeanUtils.copyProperties(inputComplianceValidateFullInvoiceInfo, tInInvoice51);
                        tInInvoice51.setFileAddress(inputComplianceValidateFullInvoiceInfo.getOfficialfileUrl());
                        tInInvoice51.setInvoiceType(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode());
                        tInInvoice51.setInvoiceTypeName(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getName());
                        tInInvoice51.setNoteType(NoteType.ZENGZHISHUI.getCode()+"");
                        tInInvoice51.setNoteName(NoteType.ZENGZHISHUI.getName());
                        tInInvoice51.setElectronicNo(inputComplianceValidateFullInvoiceInfo.getEInvoiceNumber());
                        tInInvoice51.setEticketNumber(inputComplianceValidateFullInvoiceInfo.getETicketNumber());
                        tInInvoice51.setInvoiceDate(inputComplianceValidateFullInvoiceInfo.getBillingDate());
                        tInInvoice51.setPurchaserName(inputComplianceValidateFullInvoiceInfo.getPurchaserName());
                        tInInvoice51.setPurchaserTaxNo(inputComplianceValidateFullInvoiceInfo.getPurchaserTaxNo());
                        tInInvoice51.setSaleName(inputComplianceValidateFullInvoiceInfo.getSalesName());
                        tInInvoice51.setSaleTaxNo(inputComplianceValidateFullInvoiceInfo.getSalesTaxNo());
                        tInInvoice51.setRemark(inputComplianceValidateFullInvoiceInfo.getRemarks());
                        tInInvoice51.setTotalAmount(new BigDecimal(inputComplianceValidateFullInvoiceInfo.getTotalAmount()));
                        tInInvoice51.setTotalTax(inputComplianceValidateFullInvoiceInfo.getTotalTax());
                        tInInvoice51.setAmountTax(new BigDecimal(inputComplianceValidateFullInvoiceInfo.getAmountTax()));
                        tInInvoice51.setDeductTax(tInInvoice.getDeductTax());
                        // FIXME 是否 Drawer = Name
                        tInInvoice51.setDrawer(inputComplianceValidateFullInvoiceInfo.getName());
                        // FIXME 是否 LeaveCity = FromStation
                        tInInvoice51.setLeaveCity(inputComplianceValidateFullInvoiceInfo.getFromStation());
                        // FIXME 是否 ArriveCity = ToStation
                        tInInvoice51.setArriveCity(inputComplianceValidateFullInvoiceInfo.getToStation());
                        // 车次
                        tInInvoice51.setTrainNumber(inputComplianceValidateFullInvoiceInfo.getTrainNumber());
                        // 身份证号码/组织机构代码
                        tInInvoice51.setIdNum(inputComplianceValidateFullInvoiceInfo.getIdCardNo());
                        // 席别
                        tInInvoice51.setTrainSeat(inputComplianceValidateFullInvoiceInfo.getSeatLevel());
                        // 出发时间(铁路电子客票
                        tInInvoice51.setLeaveTime(inputComplianceValidateFullInvoiceInfo.getTravelDate());
                        // FIXME 到达时间？
                        tInInvoice51.setArriveTime(null);
                        // 影像
                        tInInvoice51.setHasPicture(0);
                        tInInvoice51.setHasPictureName("无");
                        // FIXME 查验状态
                        tInInvoice51.setInspectionTime(DateUtils.getNowDate());
                        tInInvoice51.setInspectionStatus(1);
                        tInInvoice51.setInspectionStatusName("查验通过");
                        tInInvoice51.setInspectionErrorDesc("");
                        // FIXME 合规
                        tInInvoice51.setIsComplianceCollect(IsComplianceCollect.HEGUI.getCode());
                        tInInvoice51.setIsComplianceCollectName(IsComplianceCollect.HEGUI.getName());
                        tInInvoice51.setComplianceCollectDesc("");
                        // FIXME 校验
                        tInInvoice51.setVerifyStatus(VerifyStatus.CHA_YAN_TONG_GUO.getCode());
                        tInInvoice51.setVerifyStatusName(VerifyStatus.CHA_YAN_TONG_GUO.getName());
                        // 发票状态：0-正常，1-失控， 2-作废，3-红冲，4-异常，7-部分红
                        //冲，8-全额红冲
                        tInInvoice51.setInvoiceState(Integer.parseInt(inputComplianceValidateFullInvoiceInfo.getState()));
                        tInInvoice51.setInvoiceStateName(DictUtils.getDictLabel("in_invoice_type", inputComplianceValidateFullInvoiceInfo.getState()));
                        // FIXME 签收
                        tInInvoice51.setSignStatus(SignStatus.SIGNED.getCode());
                        tInInvoice51.setSignStatusName(SignStatus.SIGNED.getName());
                        // FIXME 推送时间
                        tInInvoice51.setPushTime(null);
                        //
                        tInInvoice51.setCollectinvUseType(null);
                        tInInvoice51.setId(null);
                        tInInvoice51.setInvoiceId(tInInvoice.getInvoiceId());
                    }
                    // 61:数电票（航空运输电子客票行程单）
                    TInInvoice61 tInInvoice61 = new TInInvoice61();
                    if(invoiceType.equals(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode())){
                        BeanUtils.copyProperties(tInInvoice, tInInvoice61);
                        // FIXME 字段对应需要重新检查，需要手动指定字段赋值
                        BeanUtils.copyProperties(inputComplianceValidateFullInvoiceInfo, tInInvoice61);
                        tInInvoice61.setInvoiceType(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode());
                        tInInvoice61.setInvoiceTypeName(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getName());
                        tInInvoice61.setNoteType(NoteType.ZENGZHISHUI.getCode()+"");
                        tInInvoice61.setNoteName(NoteType.ZENGZHISHUI.getName());
                        tInInvoice61.setElectronicNo(inputComplianceValidateFullInvoiceInfo.getEInvoiceNumber());
                        tInInvoice61.setEticketNumber(inputComplianceValidateFullInvoiceInfo.getETicketNumber());
                        tInInvoice61.setInvoiceDate(inputComplianceValidateFullInvoiceInfo.getBillingDate());
                        tInInvoice61.setUseRemark(inputComplianceValidateFullInvoiceInfo.getRemarks());
                        tInInvoice61.setTotalAmount(new BigDecimal(inputComplianceValidateFullInvoiceInfo.getTotalAmount()));
                        tInInvoice61.setTotalTax(inputComplianceValidateFullInvoiceInfo.getTotalTax());
                        // FIXME 其他税费
                        // tInInvoice61.setOtherTax(?);
                        tInInvoice61.setAmountTax(new BigDecimal(inputComplianceValidateFullInvoiceInfo.getAmountTax()));
                        // FIXME 是否 DeductTax = EffectiveTax
                        tInInvoice61.setDeductTax(tInInvoice.getDeductTax());
                        // FIXME 是否 Drawer = Name
                        tInInvoice61.setDrawer(inputComplianceValidateFullInvoiceInfo.getName());
                        // FIXME 民航发展基金
                        // tInInvoice61.setCivilAviationFund(?);
                        // FIXME 民航发展基金
                        // tInInvoice61.setCivilAviationFund(?);
                        // FIXME 是否 LeaveCity = FromStation
                        tInInvoice61.setLeaveCity(inputComplianceValidateFullInvoiceInfo.getFromStation());
                        // FIXME 是否 ArriveCity = ToStation
                        tInInvoice61.setArriveCity(inputComplianceValidateFullInvoiceInfo.getToStation());
                        // 航班
                        tInInvoice61.setTrainNumber(inputComplianceValidateFullInvoiceInfo.getTrainNumber());
                        // FIXME 车牌号
                        // tInInvoice61.setCarNo(?);
                        // 身份证号码/组织机构代码
                        tInInvoice61.setIdNum(inputComplianceValidateFullInvoiceInfo.getIdCardNo());
                        // 席别
                        tInInvoice61.setTrainSeat(inputComplianceValidateFullInvoiceInfo.getSeatLevel());
                        // 出发时间(铁路电子客票
                        tInInvoice61.setLeaveTime(inputComplianceValidateFullInvoiceInfo.getTravelDate());
                        // FIXME 到达时间？
                        tInInvoice61.setArriveTime(null);
                        // FIXME 保险费
                        // tInInvoice61.setPremium(?);
                        // 影像
                        tInInvoice61.setHasPicture(0);
                        tInInvoice61.setHasPictureName("无");
                        // FIXME 查验状态
                        tInInvoice61.setInspectionTime(DateUtils.getNowDate());
                        tInInvoice61.setInspectionStatus(1);
                        tInInvoice61.setInspectionStatusName("查验通过");
                        tInInvoice61.setInspectionErrorDesc("");
                        // FIXME 合规
                        tInInvoice61.setIsComplianceCollect(IsComplianceCollect.HEGUI.getCode());
                        tInInvoice61.setIsComplianceCollectName(IsComplianceCollect.HEGUI.getName());
                        tInInvoice61.setComplianceCollectDesc("");
                        // FIXME 校验
                        tInInvoice61.setVerifyStatus(VerifyStatus.CHA_YAN_TONG_GUO.getCode());
                        tInInvoice61.setVerifyStatusName(VerifyStatus.CHA_YAN_TONG_GUO.getName());
                        // 发票状态：0-正常，1-失控， 2-作废，3-红冲，4-异常，7-部分红
                        //冲，8-全额红冲
                        tInInvoice61.setInvoiceState(Integer.parseInt(inputComplianceValidateFullInvoiceInfo.getState()));
                        tInInvoice61.setInvoiceStateName(DictUtils.getDictLabel("in_invoice_type", inputComplianceValidateFullInvoiceInfo.getState()));

                        // 发票状态：0-正常，1-失控， 2-作废，3-红冲，4-异常，7-部分红
                        //冲，8-全额红冲
                        tInInvoice61.setInvoiceState(Integer.parseInt(inputComplianceValidateFullInvoiceInfo.getState()));
                        tInInvoice61.setInvoiceStateName(DictUtils.getDictLabel("in_invoice_type", inputComplianceValidateFullInvoiceInfo.getState()));

                        tInInvoice61.setId(null);
                        tInInvoice61.setInvoiceId(tInInvoice.getInvoiceId());
                    }
                    //TODO 其他副表

                    List<TInInvoiceEntry> tInInvoiceEntryList = new ArrayList<>();
                    List<InputComplianceValidateInvoice> invoiceList = inputComplianceValidateFullInvoiceInfo.getInvoiceList();
                    for(InputComplianceValidateInvoice inputComplianceValidateInvoice : invoiceList){
                        TInInvoiceEntry tInInvoiceEntry = new TInInvoiceEntry();
                        BeanUtils.copyProperties(tInInvoice, tInInvoiceEntry);
                        tInInvoiceEntry.setId(null);
                        // 单价
                        tInInvoiceEntry.setUnitPrice(inputComplianceValidateInvoice.getUnitPrice() != null ? new BigDecimal(inputComplianceValidateInvoice.getUnitPrice()) : null);
                        // 行号
                        tInInvoiceEntry.setRowNo(inputComplianceValidateInvoice.getRowNo());
                        // 税率
                        tInInvoiceEntry.setTaxRate(inputComplianceValidateInvoice.getTaxRate() != null ? new BigDecimal(inputComplianceValidateInvoice.getTaxRate()) : null);
                        // 金额
                        tInInvoiceEntry.setAmount(inputComplianceValidateInvoice.getAmount() != null ? new BigDecimal(inputComplianceValidateInvoice.getAmount()) : null);
                        // 单位
                        tInInvoiceEntry.setUnit(inputComplianceValidateInvoice.getUnit());
                        // 数量
                        tInInvoiceEntry.setQuantity(inputComplianceValidateInvoice.getQuantity() != null ? new BigDecimal(inputComplianceValidateInvoice.getQuantity()) : null);
                        // 规格型号
                        tInInvoiceEntry.setSpecificationModel(inputComplianceValidateInvoice.getSpecificationModel());
                        // 税额
                        tInInvoiceEntry.setTax(inputComplianceValidateInvoice.getTax() != null ? new BigDecimal(inputComplianceValidateInvoice.getTax()) : null);
                        // 货物或应税劳务名称
                        tInInvoiceEntry.setCommodityName(inputComplianceValidateInvoice.getCommodityName());
                        // 货物或应税劳务编码
                        tInInvoiceEntry.setCommodityCode(inputComplianceValidateInvoice.getCommodityCode());
                        tInInvoiceEntryList.add(tInInvoiceEntry);

                        List<TInInvoice61Entry> tInInvoice61EntryList = new ArrayList<>();
                        if(invoiceType.equals(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_AIR_TRANSPORT_E_TICKET.getCode())){
                            TInInvoice61Entry tInInvoice61Entry = new TInInvoice61Entry();
                            BeanUtils.copyProperties(tInInvoice61, tInInvoice61Entry);
                            // FIXME 字段对应需要重新检查，需要手动指定字段赋值
                            BeanUtils.copyProperties(inputComplianceValidateInvoice, tInInvoice61Entry);
                            tInInvoice61Entry.setFromStation(inputComplianceValidateInvoice.getFromCity());
                            tInInvoice61Entry.setToStation(inputComplianceValidateInvoice.getToCity());
                            // 航班号
                            tInInvoice61Entry.setFlightNo(inputComplianceValidateInvoice.getFlightNumber());
                            tInInvoice61Entry.setTravelDate(inputComplianceValidateInvoice.getCarriageDate());
                            tInInvoice61Entry.setTravelTime(inputComplianceValidateInvoice.getFlightDate());
                            tInInvoice61Entry.setSeatLevel(inputComplianceValidateInvoice.getSeatLevel());
                            tInInvoice61.setId(null);
                            tInInvoice61.setInvoiceId(tInInvoice.getInvoiceId());
                            tInInvoice61EntryList.add(tInInvoice61Entry);
                        }
                        tInInvoice61.setTInInvoice61EntryList(tInInvoice61EntryList);
                    }
                    tInInvoice.setTInInvoiceEntryList(tInInvoiceEntryList);
                    tInInvoice.setUpdateBy("查验接口");
                    tInInvoice.setUpdateTime(DateUtils.getNowDate());
                    if(updateTInInvoice(tInInvoice) == 1) {
                        // 51:数电票（铁路电子客票） -增
                        // 61:数电票（航空运输电子客票行程单） -增
                        // 保存副表
                        if(invoiceType.equals(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode())){
                            tInInvoice51Service.insertTInInvoice51(tInInvoice51);
                        }
                        if(invoiceType.equals(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode())){
                            tInInvoice61Service.insertTInInvoice61(tInInvoice61);
                        }
                    }
                }
            } catch (BaseException e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }

        }

        // Todo 查询符合条件的销项发票
    }

    /**
     * 从百望）同步系统内所有税号的可抵扣发票
     */
    @Override
    public void invoiceDeductionDataSyncFromBaiwang() {
        // 查询系统内所有的分公司
        TSysSite tSysSiteCondition = new TSysSite();
        List<TSysSite> sysSiteList = tSysSiteService.selectTSysSiteList(tSysSiteCondition);
        for(TSysSite tSysSite : sysSiteList){
            if(!StringUtils.isEmpty(tSysSite.getTaxNumber())){
                logger.info("分公司 {} 税号 {} 开始同步 抵扣类发票信息", tSysSite.getSiteName(), tSysSite.getTaxNumber());
                InputInvoicedataSyncResponse inputInvoicedataSyncResponse = BaiwangUtils.invoiceDeductionDataSync(tSysSite.getTaxNumber());
                if(!inputInvoicedataSyncResponse.getSuccess()){
                    throw new ServiceException("抵扣类发票取数接口异常：" + inputInvoicedataSyncResponse.getErrorResponse().getMessage());
                }
                InputInvoicedataSync response = inputInvoicedataSyncResponse.getResponse();
                // 任务编号
                String taskNo = response.getTaskNo();
                String taxNo = tSysSite.getTaxNumber();
                try {
                    // 返回的发票列表
                    List<InputInvoicedataSyncInvoice> inputInvoicedataSyncInvoiceList = response.getInvoiceList();
                    for(InputInvoicedataSyncInvoice inputInvoicedataSyncInvoice : inputInvoicedataSyncInvoiceList) {
                        // 发票种类
                        // 01-增值税专用发票;
                        // 02-货运运输业增值税专用发票;
                        // 03-机动车销售统一  发票;
                        // 08-增值税电子专用发票;
                        // 14-道路通行费电子普通发票;
                        // 31-数电票（增值税专用发票）;
                        // 51 数电票（铁路电子客票）;
                        // 61 数电票（航空运输 电子客票行程单）;
                        // 83 数电票（机动车销售统一发票）;
                        // 85 数电纸质发票（增值税专用发票）;
                        // 87 数电纸质发票（机动车销售统一发票）;
                        String invoiceType = inputInvoicedataSyncInvoice.getInvoiceType();
                        String certificationType = inputInvoicedataSyncInvoice.getCertificationType();

                        // 发票代码
                        String invoiceCode = inputInvoicedataSyncInvoice.getInvoiceCode();
                        // 发票号码
                        String invoiceNumber = inputInvoicedataSyncInvoice.getInvoiceNumber();
                        /*
                            检查该票是否已经在进项池内
                            若已存在 则修改可抵扣标记为 可抵扣
                            若不存在 则直接入池，可抵扣标记初始化 可抵扣
                         */
                        TInInvoice tInInvoice = selectTInInvoiceByInvoiceNumber(invoiceNumber);
                        if(!Objects.isNull(tInInvoice)){
                            tInInvoice.setUpdateTime(DateUtils.getNowDate());
                            // 发票状态不一致
                            if(!tInInvoice.getInvoiceState().equals(Integer.parseInt(inputInvoicedataSyncInvoice.getState()))){
                                logger.warn("发票 {} 本地状态{} 与抵扣取数返回状态 {} 不一致", tInInvoice.getInvoiceNo(), tInInvoice.getInvoiceState(), inputInvoicedataSyncInvoice.getState());
                            }
                            // 合计税额不一致
                            if(!tInInvoice.getTotalTax().equals(new BigDecimal(inputInvoicedataSyncInvoice.getTotalTax()))){
                                logger.warn("发票 {} 合计税额{} 与抵扣取数返回合计税额 {} 不一致", tInInvoice.getInvoiceNo(), tInInvoice.getTotalTax(), inputInvoicedataSyncInvoice.getTotalTax());
                            }
                            // 合计金额不一致
                            if(!tInInvoice.getTotalAmount().equals(new BigDecimal(inputInvoicedataSyncInvoice.getTotalAmount()))){
                                logger.warn("发票 {} 合计金额{} 与抵扣取数返回合计金额 {} 不一致", tInInvoice.getInvoiceNo(), tInInvoice.getTotalAmount(), inputInvoicedataSyncInvoice.getTotalAmount());
                            }
                        } else {
                            tInInvoice = new TInInvoice();
                            tInInvoice.setInvoiceNo(invoiceNumber);
                            tInInvoice.setInvoiceCode(invoiceCode);
                            // 处理状态初始化为 待审核，需要条用查询接口返回明细
                            tInInvoice.setProcessStatus(ProcessStatus.PENDING_REVIEW.getCode());
                            tInInvoice.setProcessStatusName(ProcessStatus.PENDING_REVIEW.getName());
                            tInInvoice.setCreateBy("抵扣取数同步");
                            // 采集状态 - 未采集
                            tInInvoice.setCollectStatus(CollectStatus.WEI_CAI_JI.getCode());
                            tInInvoice.setCollectStatusName(CollectStatus.WEI_CAI_JI.getName());
                        }
                        BeanUtils.copyProperties(inputInvoicedataSyncInvoice, tInInvoice);
                        // 已同步抵扣
                        tInInvoice.setIsInvoicedataSync("1");
                        // 发票类型
                        tInInvoice.setInvoiceTypeName(DictUtils.getDictLabel("in_invoice_type", inputInvoicedataSyncInvoice.getInvoiceType()));
                        //认证状态
                        tInInvoice.setDeductibleName(DictUtils.getDictLabel("deductible", inputInvoicedataSyncInvoice.getDeductible()));
                        // 发票状态
                        tInInvoice.setInvoiceState(inputInvoicedataSyncInvoice.getState());
                        tInInvoice.setInvoiceStateName(DictUtils.getDictLabel("invoice_status", inputInvoicedataSyncInvoice.getState()));
                        // 不抵扣原因
                        tInInvoice.setReasonName(DictUtils.getDictLabel("cancelnon_reason", inputInvoicedataSyncInvoice.getReason()));
                        // 平台来源
                        tInInvoice.setPlatformSourceName(DictUtils.getDictLabel("platform_source", inputInvoicedataSyncInvoice.getPlatformSource()));
                        // 开票日期
                        tInInvoice.setInvoiceDate(inputInvoicedataSyncInvoice.getBillingDate());

                        /*
                            其他字段修改
                         */
                        // 发票状态
                        tInInvoice.setInvoiceState(inputInvoicedataSyncInvoice.getState());
                        tInInvoice.setInvoiceStateName(DictUtils.getDictLabel("invoice_status", inputInvoicedataSyncInvoice.getState()));
                        // 认证类型
                        tInInvoice.setCertificationType(certificationType);
                        tInInvoice.setCertificationTypeName(DictUtils.getDictLabel("certification_type", inputInvoicedataSyncInvoice.getState()));
                        // 可抵扣税额
                        if(!Objects.isNull(inputInvoicedataSyncInvoice.getEffectiveTax())){
                            tInInvoice.setDeductTax(new BigDecimal(inputInvoicedataSyncInvoice.getEffectiveTax()));
                        }
                        //不抵扣原因
                        if(!Objects.isNull(inputInvoicedataSyncInvoice.getReason())){
                            tInInvoice.setDeductErrorRemark(DictUtils.getDictLabel("no_deduct_reason", inputInvoicedataSyncInvoice.getReason()));
                            if(inputInvoicedataSyncInvoice.getReason().equals("5")){
                                tInInvoice.setDeductErrorRemark("其他原因：" + inputInvoicedataSyncInvoice.getReasonRemark());
                            }
                        }
                        // 合计税额
                        tInInvoice.setTotalTax(new BigDecimal(inputInvoicedataSyncInvoice.getTotalTax()));
                        // 合计金额
                        tInInvoice.setTotalAmount(new BigDecimal(inputInvoicedataSyncInvoice.getTotalAmount()));
                        // 销方名称
                        tInInvoice.setSaleName(inputInvoicedataSyncInvoice.getSalesTaxName());
                        // 销方税号
                        tInInvoice.setSaleTaxNo(inputInvoicedataSyncInvoice.getSalesTaxNo());
                        // 发票代码
                        tInInvoice.setInvoiceCode(invoiceCode);
                        // 平台来源
                        tInInvoice.setPlatformSource(inputInvoicedataSyncInvoice.getPlatformSource());
                        // 买方税号
                        tInInvoice.setPurchaserTaxNo(inputInvoicedataSyncInvoice.getPurchaserTaxNo());
                        // tInInvoice.setPurchaserName(inputInvoicedataSyncInvoice.getPurchaserTaxNo());
                        if(tInInvoice.getId() != null){
                            tInInvoiceMapper.updateTInInvoice(tInInvoice);
                        } else {
                            insertTInInvoice(tInInvoice);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
               // 取数成功后，调用取数成功反馈接口
                InputInvoicedataSyncresultResponse inputInvoicedataSyncresultResponse = BaiwangUtils.invoicedataSyncresult(taskNo, tSysSite.getTaxNumber());
                if(!inputInvoicedataSyncresultResponse.getSuccess()){
                    throw new ServiceException("抵扣类发票取数确认接口异常：" + inputInvoicedataSyncResponse.getErrorResponse().getMessage());
                }
            }
            else {
                // 该分公司没有维护税号
            }
        }
    }


    /**
     * （从百望）未获取完整信息的进项发票，同步完整信息
     */
    @Override
    public void inIinvoiceDetailDataSyncFromBaiwang() {
        // 查询符合条件的进项发票
        TInInvoice tInInvoiceCondition = new TInInvoice();
        tInInvoiceCondition.setInvoiceNo("05842508");
        tInInvoiceCondition.setProcessStatus(ProcessStatus.PENDING_REVIEW.getCode());
        // tInInvoiceCondition.setInvoiceNo("05842508");
        List<TInInvoice> inInvoiceList = selectTInInvoiceList(tInInvoiceCondition);
        //
        for(TInInvoice tInInvoice : inInvoiceList){
            // 进项发票的完整信息应通过查验接口获取
            InvoiceForValidate invoiceForValidate = new InvoiceForValidate();
            // 20位 发票号码
            invoiceForValidate.setInvoiceNumber(tInInvoice.getInvoiceNo());
            // 发票代码位数为10位或12位
            invoiceForValidate.setInvoiceCode(tInInvoice.getInvoiceCode());
            invoiceForValidate.setCheckCode(tInInvoice.getCheckCode());
            // 购方税号
            invoiceForValidate.setTaxNo(tInInvoice.getPurchaserTaxNo());
            //
            invoiceForValidate.setBillingDate(tInInvoice.getInvoiceDate());
            invoiceForValidate.setTotalAmount(tInInvoice.getTotalAmount().toString());
            invoiceForValidate.setInvoiceType(tInInvoice.getInvoiceType());
            try {
                InputComplianceValidateResponse response = BaiwangUtils.validate(invoiceForValidate);
                if(!response.getSuccess()){
                    logger.error("发票 {} 查验失败 {}, {}", tInInvoice.getInvoiceNo(), response.getErrorResponse().getCode(), response.getErrorResponse().getMessage());
                } else {
                    // 解析返回
                    InputComplianceValidate inputComplianceValidate = response.getResponse();
                    // 发票类型 即查验接口不返回非增值税发票
                    // 01:增值税专用发票
                    // 03:机动车销售统一发票
                    // 04:增值税普通发票
                    // 08:增值税电子专用发票
                    // 10:增值税电子普通发票
                    // 11:增值税普通发票(卷式)
                    // 14: 道路通行费电子普通发票
                    // 15:二手车销售统一发票
                    // 31:数电票（增值税专用发票）
                    // 32:数电票（普通发票）
                    // 51: 数电票（铁路电子客票）
                    // 61:数电票（航空运输电子客票行程单）
                    // 85 :数电纸质发票（增值税专用发票）
                    // 86:数电纸质发票（普通发票）
                    String invoiceType = inputComplianceValidate.getInvoiceType();
                    // 发票数据
                    InputComplianceValidateFullInvoiceInfo inputComplianceValidateFullInvoiceInfo = inputComplianceValidate.getData();

                    // 购方名称
                    tInInvoice.setPurchaserName(inputComplianceValidateFullInvoiceInfo.getPurchaserName());
                    // 购方开户行账户
                    tInInvoice.setPurchaserBank(inputComplianceValidateFullInvoiceInfo.getPurchaserBank());
                    // 所属行政区名称
                    tInInvoice.setAdministrativeDivisionName(inputComplianceValidateFullInvoiceInfo.getAdministrativeDivisionName());
                    // 机器编号
                    tInInvoice.setMachineCode(inputComplianceValidateFullInvoiceInfo.getMachineCode());
                    // 收货人
                    tInInvoice.setReceivingClerk(inputComplianceValidateFullInvoiceInfo.getReceivingClerk());
                    // 成品油标记
                    tInInvoice.setOilMark(inputComplianceValidateFullInvoiceInfo.getOilMark());
                    // 校验码
                    tInInvoice.setCheckCode(inputComplianceValidateFullInvoiceInfo.getCheckCode());
                    // 销方地址电话
                    tInInvoice.setSalesAddressPhone(inputComplianceValidateFullInvoiceInfo.getSalesAddressPhone());
                    // 销方开户行
                    tInInvoice.setSalesBank(inputComplianceValidateFullInvoiceInfo.getSalesBank());
                    // 销方开户行账户
                    tInInvoice.setSalesBankNo(inputComplianceValidateFullInvoiceInfo.getSalesBankNo());
                    // 数电发票号码
                    tInInvoice.setEInvoiceNumber(inputComplianceValidateFullInvoiceInfo.getEInvoiceNumber());
                    // 购方地址电话
                    tInInvoice.setPurchaserAddressPhone(inputComplianceValidateFullInvoiceInfo.getPurchaserAddressPhone());
                    // 发票状态
                    tInInvoice.setInvoiceState(inputComplianceValidateFullInvoiceInfo.getState());
                    tInInvoice.setInvoiceStateName(DictUtils.getDictLabel("in_invoice_type", inputComplianceValidateFullInvoiceInfo.getState()));
                    // t_in_invoice 对象保存
                    // FIXME 初始的报销状态？
//                    tInInvoice.setSubmitStatus(SubmitStatus.NOT_REIMBURSED.getCode());
//                    tInInvoice.setSubmitStatusName(SubmitStatus.NOT_REIMBURSED.getName());
                    // 发票备注
                    tInInvoice.setInvoiceRemark(inputComplianceValidateFullInvoiceInfo.getRemarks());
                    // 是否红票
                    // tInInvoice.setIsRed(IsRed.BLUE.getCode());
                    // 入账状态
//                    tInInvoice.setAccountStatus(AccountStatus.NOT_ACCOUNTED.getCode());
//                    tInInvoice.setAccountStatusName(AccountStatus.NOT_ACCOUNTED.getName());
                    // 处理状态
                    tInInvoice.setProcessStatus(ProcessStatus.INVOICED.getCode());
                    tInInvoice.setProcessStatusName(ProcessStatus.INVOICED.getName());

                    // 签收状态
//                    tInInvoice.setSignStatus(SignStatus.SIGNED.getCode());
//                    tInInvoice.setSignStatusName(SignStatus.SIGNED.getName());

                    // 明细
                    // 51:数电票（铁路电子客票）
                    TInInvoice51 tInInvoice51 = new TInInvoice51();
                    if(invoiceType.equals(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode())){
                        BeanUtils.copyProperties(tInInvoice, tInInvoice51);
                        // FIXME 字段对应需要重新检查，需要手动指定字段赋值
                        BeanUtils.copyProperties(inputComplianceValidateFullInvoiceInfo, tInInvoice51);
                        tInInvoice51.setFileAddress(inputComplianceValidateFullInvoiceInfo.getOfficialfileUrl());
                        tInInvoice51.setInvoiceType(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode());
                        tInInvoice51.setInvoiceTypeName(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getName());
                        tInInvoice51.setNoteType(NoteType.ZENGZHISHUI.getCode()+"");
                        tInInvoice51.setNoteName(NoteType.ZENGZHISHUI.getName());
                        tInInvoice51.setElectronicNo(inputComplianceValidateFullInvoiceInfo.getEInvoiceNumber());
                        tInInvoice51.setEticketNumber(inputComplianceValidateFullInvoiceInfo.getETicketNumber());
                        tInInvoice51.setInvoiceDate(inputComplianceValidateFullInvoiceInfo.getBillingDate());
                        tInInvoice51.setPurchaserName(inputComplianceValidateFullInvoiceInfo.getPurchaserName());
                        tInInvoice51.setPurchaserTaxNo(inputComplianceValidateFullInvoiceInfo.getPurchaserTaxNo());
                        tInInvoice51.setSaleName(inputComplianceValidateFullInvoiceInfo.getSalesName());
                        tInInvoice51.setSaleTaxNo(inputComplianceValidateFullInvoiceInfo.getSalesTaxNo());
                        tInInvoice51.setRemark(inputComplianceValidateFullInvoiceInfo.getRemarks());
                        tInInvoice51.setTotalAmount(new BigDecimal(inputComplianceValidateFullInvoiceInfo.getTotalAmount()));
                        tInInvoice51.setTotalTax(inputComplianceValidateFullInvoiceInfo.getTotalTax());
                        tInInvoice51.setAmountTax(new BigDecimal(inputComplianceValidateFullInvoiceInfo.getAmountTax()));
                        tInInvoice51.setDeductTax(tInInvoice.getDeductTax());
                        // FIXME 是否 Drawer = Name
                        tInInvoice51.setDrawer(inputComplianceValidateFullInvoiceInfo.getName());
                        // FIXME 是否 LeaveCity = FromStation
                        tInInvoice51.setLeaveCity(inputComplianceValidateFullInvoiceInfo.getFromStation());
                        // FIXME 是否 ArriveCity = ToStation
                        tInInvoice51.setArriveCity(inputComplianceValidateFullInvoiceInfo.getToStation());
                        // 车次
                        tInInvoice51.setTrainNumber(inputComplianceValidateFullInvoiceInfo.getTrainNumber());
                        // 身份证号码/组织机构代码
                        tInInvoice51.setIdNum(inputComplianceValidateFullInvoiceInfo.getIdCardNo());
                        // 席别
                        tInInvoice51.setTrainSeat(inputComplianceValidateFullInvoiceInfo.getSeatLevel());
                        // 出发时间(铁路电子客票
                        tInInvoice51.setLeaveTime(inputComplianceValidateFullInvoiceInfo.getTravelDate());
                        // FIXME 到达时间？
                        tInInvoice51.setArriveTime(null);
                        // 影像
                        tInInvoice51.setHasPicture(0);
                        tInInvoice51.setHasPictureName("无");
                        // FIXME 查验状态
                        tInInvoice51.setInspectionTime(DateUtils.getNowDate());
                        tInInvoice51.setInspectionStatus(1);
                        tInInvoice51.setInspectionStatusName("查验通过");
                        tInInvoice51.setInspectionErrorDesc("");
                        // FIXME 合规
                        tInInvoice51.setIsComplianceCollect(IsComplianceCollect.HEGUI.getCode());
                        tInInvoice51.setIsComplianceCollectName(IsComplianceCollect.HEGUI.getName());
                        tInInvoice51.setComplianceCollectDesc("");
                        // FIXME 校验
                        tInInvoice51.setVerifyStatus(VerifyStatus.CHA_YAN_TONG_GUO.getCode());
                        tInInvoice51.setVerifyStatusName(VerifyStatus.CHA_YAN_TONG_GUO.getName());
                        // 发票状态：0-正常，1-失控， 2-作废，3-红冲，4-异常，7-部分红
                        //冲，8-全额红冲
                        tInInvoice51.setInvoiceState(Integer.parseInt(inputComplianceValidateFullInvoiceInfo.getState()));
                        tInInvoice51.setInvoiceStateName(DictUtils.getDictLabel("in_invoice_type", inputComplianceValidateFullInvoiceInfo.getState()));
                        // FIXME 签收
                        tInInvoice51.setSignStatus(SignStatus.SIGNED.getCode());
                        tInInvoice51.setSignStatusName(SignStatus.SIGNED.getName());
                        // FIXME 推送时间
                        tInInvoice51.setPushTime(null);
                        //
                        tInInvoice51.setCollectinvUseType(null);
                        tInInvoice51.setId(null);
                        tInInvoice51.setInvoiceId(tInInvoice.getInvoiceId());
                    }
                    // 61:数电票（航空运输电子客票行程单）
                    TInInvoice61 tInInvoice61 = new TInInvoice61();
                    if(invoiceType.equals(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode())){
                        BeanUtils.copyProperties(tInInvoice, tInInvoice61);
                        // FIXME 字段对应需要重新检查，需要手动指定字段赋值
                        BeanUtils.copyProperties(inputComplianceValidateFullInvoiceInfo, tInInvoice61);
                        tInInvoice61.setInvoiceType(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode());
                        tInInvoice61.setInvoiceTypeName(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getName());
                        tInInvoice61.setNoteType(NoteType.ZENGZHISHUI.getCode()+"");
                        tInInvoice61.setNoteName(NoteType.ZENGZHISHUI.getName());
                        tInInvoice61.setElectronicNo(inputComplianceValidateFullInvoiceInfo.getEInvoiceNumber());
                        tInInvoice61.setEticketNumber(inputComplianceValidateFullInvoiceInfo.getETicketNumber());
                        tInInvoice61.setInvoiceDate(inputComplianceValidateFullInvoiceInfo.getBillingDate());
                        tInInvoice61.setUseRemark(inputComplianceValidateFullInvoiceInfo.getRemarks());
                        tInInvoice61.setTotalAmount(new BigDecimal(inputComplianceValidateFullInvoiceInfo.getTotalAmount()));
                        tInInvoice61.setTotalTax(inputComplianceValidateFullInvoiceInfo.getTotalTax());
                        // FIXME 其他税费
                        // tInInvoice61.setOtherTax(?);
                        tInInvoice61.setAmountTax(new BigDecimal(inputComplianceValidateFullInvoiceInfo.getAmountTax()));
                        // FIXME 是否 DeductTax = EffectiveTax
                        tInInvoice61.setDeductTax(tInInvoice.getDeductTax());
                        // FIXME 是否 Drawer = Name
                        tInInvoice61.setDrawer(inputComplianceValidateFullInvoiceInfo.getName());
                        // FIXME 民航发展基金
                        // tInInvoice61.setCivilAviationFund(?);
                        // FIXME 民航发展基金
                        // tInInvoice61.setCivilAviationFund(?);
                        // FIXME 是否 LeaveCity = FromStation
                        tInInvoice61.setLeaveCity(inputComplianceValidateFullInvoiceInfo.getFromStation());
                        // FIXME 是否 ArriveCity = ToStation
                        tInInvoice61.setArriveCity(inputComplianceValidateFullInvoiceInfo.getToStation());
                        // 航班
                        tInInvoice61.setTrainNumber(inputComplianceValidateFullInvoiceInfo.getTrainNumber());
                        // FIXME 车牌号
                        // tInInvoice61.setCarNo(?);
                        // 身份证号码/组织机构代码
                        tInInvoice61.setIdNum(inputComplianceValidateFullInvoiceInfo.getIdCardNo());
                        // 席别
                        tInInvoice61.setTrainSeat(inputComplianceValidateFullInvoiceInfo.getSeatLevel());
                        // 出发时间(铁路电子客票
                        tInInvoice61.setLeaveTime(inputComplianceValidateFullInvoiceInfo.getTravelDate());
                        // FIXME 到达时间？
                        tInInvoice61.setArriveTime(null);
                        // FIXME 保险费
                        // tInInvoice61.setPremium(?);
                        // 影像
                        tInInvoice61.setHasPicture(0);
                        tInInvoice61.setHasPictureName("无");
                        // FIXME 查验状态
                        tInInvoice61.setInspectionTime(DateUtils.getNowDate());
                        tInInvoice61.setInspectionStatus(1);
                        tInInvoice61.setInspectionStatusName("查验通过");
                        tInInvoice61.setInspectionErrorDesc("");
                        // FIXME 合规
                        tInInvoice61.setIsComplianceCollect(IsComplianceCollect.HEGUI.getCode());
                        tInInvoice61.setIsComplianceCollectName(IsComplianceCollect.HEGUI.getName());
                        tInInvoice61.setComplianceCollectDesc("");
                        // FIXME 校验
                        tInInvoice61.setVerifyStatus(VerifyStatus.CHA_YAN_TONG_GUO.getCode());
                        tInInvoice61.setVerifyStatusName(VerifyStatus.CHA_YAN_TONG_GUO.getName());
                        // 发票状态：0-正常，1-失控， 2-作废，3-红冲，4-异常，7-部分红
                        //冲，8-全额红冲
                        tInInvoice61.setInvoiceState(Integer.parseInt(inputComplianceValidateFullInvoiceInfo.getState()));
                        tInInvoice61.setInvoiceStateName(DictUtils.getDictLabel("in_invoice_type", inputComplianceValidateFullInvoiceInfo.getState()));

                        // 发票状态：0-正常，1-失控， 2-作废，3-红冲，4-异常，7-部分红
                        //冲，8-全额红冲
                        tInInvoice61.setInvoiceState(Integer.parseInt(inputComplianceValidateFullInvoiceInfo.getState()));
                        tInInvoice61.setInvoiceStateName(DictUtils.getDictLabel("in_invoice_type", inputComplianceValidateFullInvoiceInfo.getState()));

                        tInInvoice61.setId(null);
                        tInInvoice61.setInvoiceId(tInInvoice.getInvoiceId());
                    }
                    //TODO 其他副表

                    List<TInInvoiceEntry> tInInvoiceEntryList = new ArrayList<>();
                    List<InputComplianceValidateInvoice> invoiceList = inputComplianceValidateFullInvoiceInfo.getInvoiceList();
                    for(InputComplianceValidateInvoice inputComplianceValidateInvoice : invoiceList){
                        TInInvoiceEntry tInInvoiceEntry = new TInInvoiceEntry();
                        BeanUtils.copyProperties(tInInvoice, tInInvoiceEntry);
                        tInInvoiceEntry.setId(null);
                        // 单价
                        tInInvoiceEntry.setUnitPrice(inputComplianceValidateInvoice.getUnitPrice() != null ? new BigDecimal(inputComplianceValidateInvoice.getUnitPrice()) : null);
                        // 行号
                        tInInvoiceEntry.setRowNo(inputComplianceValidateInvoice.getRowNo());
                        // 税率
                        tInInvoiceEntry.setTaxRate(inputComplianceValidateInvoice.getTaxRate() != null ? new BigDecimal(inputComplianceValidateInvoice.getTaxRate()) : null);
                        // 金额
                        tInInvoiceEntry.setAmount(inputComplianceValidateInvoice.getAmount() != null ? new BigDecimal(inputComplianceValidateInvoice.getAmount()) : null);
                        // 单位
                        tInInvoiceEntry.setUnit(inputComplianceValidateInvoice.getUnit());
                        // 数量
                        tInInvoiceEntry.setQuantity(inputComplianceValidateInvoice.getQuantity() != null ? new BigDecimal(inputComplianceValidateInvoice.getQuantity()) : null);
                        // 规格型号
                        tInInvoiceEntry.setSpecificationModel(inputComplianceValidateInvoice.getSpecificationModel());
                        // 税额
                        tInInvoiceEntry.setTax(inputComplianceValidateInvoice.getTax() != null ? new BigDecimal(inputComplianceValidateInvoice.getTax()) : null);
                        // 货物或应税劳务名称
                        tInInvoiceEntry.setCommodityName(inputComplianceValidateInvoice.getCommodityName());
                        // 货物或应税劳务编码
                        tInInvoiceEntry.setCommodityCode(inputComplianceValidateInvoice.getCommodityCode());
                        tInInvoiceEntryList.add(tInInvoiceEntry);

                        List<TInInvoice61Entry> tInInvoice61EntryList = new ArrayList<>();
                        if(invoiceType.equals(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_AIR_TRANSPORT_E_TICKET.getCode())){
                            TInInvoice61Entry tInInvoice61Entry = new TInInvoice61Entry();
                            BeanUtils.copyProperties(tInInvoice61, tInInvoice61Entry);
                            // FIXME 字段对应需要重新检查，需要手动指定字段赋值
                            BeanUtils.copyProperties(inputComplianceValidateInvoice, tInInvoice61Entry);
                            tInInvoice61Entry.setFromStation(inputComplianceValidateInvoice.getFromCity());
                            tInInvoice61Entry.setToStation(inputComplianceValidateInvoice.getToCity());
                            // 航班号
                            tInInvoice61Entry.setFlightNo(inputComplianceValidateInvoice.getFlightNumber());
                            tInInvoice61Entry.setTravelDate(inputComplianceValidateInvoice.getCarriageDate());
                            tInInvoice61Entry.setTravelTime(inputComplianceValidateInvoice.getFlightDate());
                            tInInvoice61Entry.setSeatLevel(inputComplianceValidateInvoice.getSeatLevel());
                            tInInvoice61.setId(null);
                            tInInvoice61.setInvoiceId(tInInvoice.getInvoiceId());
                            tInInvoice61EntryList.add(tInInvoice61Entry);
                        }
                        tInInvoice61.setTInInvoice61EntryList(tInInvoice61EntryList);
                    }
                    tInInvoice.setTInInvoiceEntryList(tInInvoiceEntryList);
                    tInInvoice.setUpdateBy("查验接口");
                    tInInvoice.setUpdateTime(DateUtils.getNowDate());
                    if(updateTInInvoice(tInInvoice) == 1) {
                        // 51:数电票（铁路电子客票） -增
                        // 61:数电票（航空运输电子客票行程单） -增
                        // 保存副表
                        if(invoiceType.equals(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode())){
                            tInInvoice51Service.insertTInInvoice51(tInInvoice51);
                        }
                        if(invoiceType.equals(InInvoiceType.DIGITAL_ELECTRIC_INVOICE_RAILWAY_E_TICKET.getCode())){
                            tInInvoice61Service.insertTInInvoice61(tInInvoice61);
                        }
                    }
                }
            } catch (BaseException e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }

        }
    }

    /**
     * （从百望）同步历史进项发票
     */
    @Override
    public void inIinvoiceHisDataSyncFromBaiwang(int month) {
// 查询系统内所有的分公司
        TSysSite tSysSiteCondition = new TSysSite();
        List<TSysSite> sysSiteList = tSysSiteService.selectTSysSiteList(tSysSiteCondition);
        for(TSysSite tSysSite : sysSiteList) {
            if (StringUtils.isEmpty(tSysSite.getTaxNumber())) {
                // 循环月份
                for(int i=month ; i>=0 ; i--){
                    String invoiceDate = DateUtils.getMonthStr(i*(-1));
                    // 调用查询历史发票页码接口
                    ChannelInvoicedataGetpagenoResponse channelInvoicedataGetpagenoResponse = BaiwangUtils.getpageno(tSysSite.getTaxNumber(), "month", invoiceDate, "input_vat");
                    if(!channelInvoicedataGetpagenoResponse.getSuccess()){
                        throw new ServiceException("历史发票页码获取接口异常：" + channelInvoicedataGetpagenoResponse.getErrorResponse().getMessage());
                    }
                    List<ChannelInvoicedataGetpageno> channelInvoicedataGetpagenoList = channelInvoicedataGetpagenoResponse.getResponse();
                    for(ChannelInvoicedataGetpageno channelInvoicedataGetpageno : channelInvoicedataGetpagenoList){
                        List<ChannelInvoicedataGetpagenoRealtimeDetailInfo> pageNoList = channelInvoicedataGetpageno.getPageNoList();
                        for(ChannelInvoicedataGetpagenoRealtimeDetailInfo channelInvoicedataGetpagenoRealtimeDetailInfo : pageNoList){
                            Long pageNo = channelInvoicedataGetpagenoRealtimeDetailInfo.getPageNo();
                            logger.info("查询税号 {} 第 {} 页进项历史发票" , tSysSite.getTaxNumber(), pageNo);

                            // 调用详细取数接口
                            ChannelInvoicedataGetpagedataResponse channelInvoicedataGetpagedataResponse = BaiwangUtils.getpagedata(tSysSite.getTaxNumber(), invoiceDate, "input_vat", pageNo);
                            if(!channelInvoicedataGetpagedataResponse.getSuccess()) {
                                throw new ServiceException("历史发票详细获取接口异常：" + channelInvoicedataGetpagedataResponse.getErrorResponse().getMessage());
                            }
                            List<ChannelInvoicedataGetpagedata> channelInvoicedataGetpagedataList = channelInvoicedataGetpagedataResponse.getResponse();
                            for(ChannelInvoicedataGetpagedata channelInvoicedataGetpagedata : channelInvoicedataGetpagedataList){
                            /*
                            发票类型:01:增值税专用发票 03:机动车销售统一发票 04:增值税普通
                            发票 08:增值税电子专用发票 10:增值税电子普通发票 11:增值税普通
                            发票(卷式) 14:通行费电子发票 15:二手车销售统一发票 31:数电票
                            （增值税专用发票） 32:数电票（增值税普通发票）83 数电票（机动
                            车销售统一发票） 84 数电票（二手车销售统一发票） 85 数电纸质
                            发票（增值税专用发票) 86 数电纸质发票（普通发票） 87 数电纸质
                            发票（机动车销售统一发票）88 数电纸质发票（二手车销售统一发
                            票）51 数电票（铁路电子客票） 61 数电票（航空运输电子客票行程
                            单）
                             */
                            String invoiceTypeCode = channelInvoicedataGetpagedata.getInvoiceTypeCode();

                            // TODO 若发票已经存在，则纠正更新字段 若不存在则直接入池
                            String invoiceCode = channelInvoicedataGetpagedata.getInvoiceCode();
                            String invoiceNo = channelInvoicedataGetpagedata.getInvoiceNo();
                            TInInvoice tInInvoice = selectTInInvoiceByInvoiceNumber(invoiceNo);

                            if(tInInvoice != null){
                                tInInvoice.setUpdateTime(DateUtils.getNowDate());
                                tInInvoice.setUpdateBy("历史票据同步");
                            } else {
                                tInInvoice = new TInInvoice();
                                tInInvoice.setInvoiceNo(invoiceNo);
                                tInInvoice.setInvoiceCode(invoiceCode);
                                tInInvoice.setCreateBy("历史票据同步");
                            }
                            // TODO 详细字段的填写






                            }
                        }
                    }
                }

            } else {
                // 该分公司没有维护税号
            }
        }

    }

    /**
     * 1. 请求-勾选抵扣
     * @param invoiceIds
     */
    @Override
    public void deductionApplyByInvoiceIds(String[] invoiceIds) {
        // 操作人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        logger.info("用户 {} 操作勾选抵扣, 发票集合 {}", loginUser.getUsername(), invoiceIds);
        TSysSite site = tSysSiteService.getCurrentSite();

        // 申请发票数
        Integer applyQty = 0;
        // 申请抵扣金额
        BigDecimal applyAmount = BigDecimal.ZERO;
        // 申请日期
        Date applyTime = DateUtils.getNowDate();
        // 申请人
        String applyBy = loginUser.getUser().getNickName();

        // 请求参数
        List<DeductionApplyInvoice> deductionApplyInvoiceList = new ArrayList<>();
        for(String invoiceId : invoiceIds){
            TInInvoice inInvoice = tInInvoiceMapper.selectTInInvoiceByInvoiceId(invoiceId);
            // 校验
            if(!inInvoice.getIsInvoicedataSync().equals("1")){
                throw new ServiceException("发票 " + inInvoice.getInvoiceNo() + "无法抵扣，请先执行抵扣同步");
            }
            if(inInvoice.getDeductTax() == null){
                throw new ServiceException("发票 " + inInvoice.getInvoiceNo() + "无抵扣金额，无法抵扣");
            }
            if(inInvoice.getCertificationType() == null){
                throw new ServiceException("发票 " + inInvoice.getInvoiceNo() + "无认证类型，无法抵扣");
            }
            DeductionApplyInvoice deductionApplyInvoice = new DeductionApplyInvoice();
            // 认证类型 - 抵扣
            deductionApplyInvoice.setCertificationType(CertificationType.DEDUCTION.getCode());
            // 抵扣税额
            deductionApplyInvoice.setEffectiveTax(inInvoice.getDeductTax().toString());
            //
            deductionApplyInvoice.setInvoiceNumber(inInvoice.getInvoiceNo());
            //
            deductionApplyInvoice.setInvoiceCode(inInvoice.getInvoiceCode());
            //
            deductionApplyInvoice.setPurchaserTaxNo(inInvoice.getPurchaserTaxNo());
            deductionApplyInvoiceList.add(deductionApplyInvoice);

            applyAmount = applyAmount.add(inInvoice.getDeductTax());
        }
        applyQty = deductionApplyInvoiceList.size();
        String taxNo = site.getTaxNumber();
        String period = DateUtils.getCurrentMonth();

        // 校验通过后，生成一个申请记录
        TInDeductionApply tInDeductionApply = new TInDeductionApply();
        tInDeductionApply.setCustId(site.getCustId());
        tInDeductionApply.setSiteCode(site.getSiteCode());
        tInDeductionApply.setSiteName(site.getSiteName());
        // 勾选申请
        tInDeductionApply.setApplyType(ApplyType.APPLY.getCode());
        tInDeductionApply.setApplyTypeName(ApplyType.APPLY.getName());
        // 抵扣
        tInDeductionApply.setApplyCertificationType(CertificationType.DEDUCTION.getCode());
        tInDeductionApply.setApplyCertificationTypeName(CertificationType.DEDUCTION.getName());

        tInDeductionApply.setApplyAmount(applyAmount);
        tInDeductionApply.setApplyBy(applyBy);
        tInDeductionApply.setApplyQty(applyQty);
        tInDeductionApply.setTaxNo(taxNo);
        tInDeductionApply.setPeriod(period);
        tInDeductionApply.setSuccess("");
        tInDeductionApply.setCode("");
        tInDeductionApply.setMessage("");
        // 申请记录的明细
        List<TInDeductionApplyEntry> tInDeductionApplyEntryList = new ArrayList<>();
        for(DeductionApplyInvoice deductionApplyInvoice : deductionApplyInvoiceList){
            TInDeductionApplyEntry tInDeductionApplyEntry = new TInDeductionApplyEntry();
            tInDeductionApplyEntry.setCertificationType(CertificationType.DEDUCTION.getCode());
            tInDeductionApplyEntry.setCertificationTypeName(CertificationType.DEDUCTION.getName());
            tInDeductionApplyEntry.setTaskNo(taxNo);
            tInDeductionApplyEntry.setPeriod(period);
            tInDeductionApplyEntry.setInvoiceCode(deductionApplyInvoice.getInvoiceCode());
            tInDeductionApplyEntry.setInvoiceNumber(deductionApplyInvoice.getInvoiceNumber());
            tInDeductionApplyEntry.setEinvoiceNumber(deductionApplyInvoice.geteInvoiceNumber());
            tInDeductionApplyEntry.setEffectiveTax(deductionApplyInvoice.getEffectiveTax());
            // 初始化结果业务字段
            tInDeductionApplyEntry.setTaskNo("");
            tInDeductionApplyEntry.setDeductibleDate("");
            tInDeductionApplyEntry.setDeductiblePeriod("");
            tInDeductionApplyEntry.setResultCode("");
            tInDeductionApplyEntry.setResultName("");
            tInDeductionApplyEntryList.add(tInDeductionApplyEntry);
        }
        tInDeductionApply.setTInDeductionApplyEntryList(tInDeductionApplyEntryList);
        if(tInDeductionApplyService.insertTInDeductionApply(tInDeductionApply) == 1){
            // 调用百望勾选抵扣申请接口
            InputDeductionApplyResponse inputDeductionApplyResponse = BaiwangUtils.deductionApply(taxNo, period , deductionApplyInvoiceList);
            // 返回失败
            if(!inputDeductionApplyResponse.getSuccess()){
                logger.error("勾选抵扣申请接口异常：" + inputDeductionApplyResponse.getErrorResponse().getMessage());
                // 修改勾选申请记录的结果
                tInDeductionApply.setSuccess("false");
                // 具体的错误码
                ErrorResponse errorResponse = inputDeductionApplyResponse.getErrorResponse();
                tInDeductionApply.setCode(errorResponse.getCode());
                tInDeductionApply.setMessage(errorResponse.getMessage());
                tInDeductionApply.setUpdateBy("接口返回异常");
                tInDeductionApplyService.updateTInDeductionApplyOnly(tInDeductionApply);
            }
            // 返回成功
            else {
                // 修改勾选申请记录的结果
                tInDeductionApply.setSuccess("true");
                InputDeductionApply inputDeductionApply = inputDeductionApplyResponse.getResponse();
                // 明细
                List<InputDeductionApplyTask> taskList = inputDeductionApply.getTaskList();
                for(InputDeductionApplyTask inputDeductionApplyTask : taskList){
                    for(TInDeductionApplyEntry tInDeductionApplyEntry : tInDeductionApplyEntryList){
                        if(inputDeductionApplyTask.getInvoiceNumber().equals(tInDeductionApplyEntry.getInvoiceNumber())){
                            // 设置任务号
                            tInDeductionApplyEntry.setTaskNo(inputDeductionApplyTask.getTaskNo());
                            // 更新发票认证类型-取消认证
                            TInInvoice inInvoice = selectTInInvoiceByInvoiceNumber(tInDeductionApplyEntry.getInvoiceNumber());
                            if(inInvoice != null){
                                inInvoice.setCertificationType(CertificationType.DEDUCTION.getCode());
                                inInvoice.setCertificationTypeName(CertificationType.DEDUCTION.getName());
                                inInvoice.setUpdateBy("勾选抵扣申请成功");
                                inInvoice.setUpdateTime(DateUtils.getNowDate());
                                tInInvoiceMapper.updateTInInvoice(inInvoice);
                            }
                        }
                    }
                }
                tInDeductionApply.setTInDeductionApplyEntryList(tInDeductionApplyEntryList);
               if(tInDeductionApplyService.updateTInDeductionApply(tInDeductionApply) == 1) {
                   // 更新成功后，需要查询申请结果
                   ImsAsyncManager.me().execute(ImsAsyncFactory.syncDeductionApplyResultFromBaiwang(tInDeductionApply.getDeductionId()));
               }
            }
        }
    }


    /**
     * 1. 结果-勾选抵扣申请结果查询
     * @param deductionId 申请ID
     */
    @Override
    public void deductionApplyResult(String deductionId) {
        TInDeductionApply tInDeductionApply = tInDeductionApplyService.selectTInDeductionApplyByDeductionId(deductionId);
        logger.info("勾选申请 deductionId = {} 准备同步明细的勾选申请结果", deductionId);
        if(tInDeductionApply != null){
            List<TInDeductionApplyEntry> tInDeductionApplyEntryList = tInDeductionApply.getTInDeductionApplyEntryList();
            for(TInDeductionApplyEntry tInDeductionApplyEntry : tInDeductionApplyEntryList){
                InputDeductionApplyresultResponse inputDeductionApplyresultResponse = BaiwangUtils.deductionApplyResult(tInDeductionApplyEntry.getTaxNo(), tInDeductionApplyEntry.getInvoiceCode(), tInDeductionApplyEntry.getInvoiceNumber(), tInDeductionApplyEntry.getEinvoiceNumber(), tInDeductionApplyEntry.getTaskNo());
                // 返回失败
                if(!inputDeductionApplyresultResponse.getSuccess()){
                    logger.error("勾选抵扣申请结果查询接口异常：" + inputDeductionApplyresultResponse.getErrorResponse().getMessage());
                    tInDeductionApplyEntry.setResultName("勾选抵扣申请结果查询接口异常");
                }
                else {
                    InputDeductionApplyresult inputDeductionApplyresult = inputDeductionApplyresultResponse.getResponse();
                    tInDeductionApplyEntry.setDeductiblePeriod(inputDeductionApplyresult.getDeductiblePeriod());
                    tInDeductionApplyEntry.setDeductibleDate(inputDeductionApplyresult.getDeductibleDate());
                    tInDeductionApplyEntry.setResultCode(inputDeductionApplyresult.getResultCode());
                    logger.info(inputDeductionApplyresult.getInvoiceNumber() + "抵扣结果：" + DictUtils.getDictLabel("result_code", inputDeductionApplyresult.getResultCode()));
                    tInDeductionApplyEntry.setResultName(DictUtils.getDictLabel("result_code", inputDeductionApplyresult.getResultCode()));
                    tInDeductionApplyEntry.setCertificationType(inputDeductionApplyresult.getCertificationType());
                    tInDeductionApplyEntry.setUpdateBy("抵扣申请结果返回");
                    try {
                        // 修改对应进项发抵扣状态
                        TInInvoice inInvoice = selectTInInvoiceByInvoiceNumber(tInDeductionApplyEntry.getInvoiceNumber());
                        if(inInvoice == null){
                            logger.error("发票 {} 记录缺失", tInDeductionApplyEntry.getInvoiceNumber());
                        } else {
                            // 发票认证类型必须与接口对齐，即 抵扣
                            if(inInvoice.getCertificationType().equals(inputDeductionApplyresult.getCertificationType())){
                                // 认证日期
                                inInvoice.setDeductibleDate(tInDeductionApplyEntry.getDeductibleDate());
                                // 税款所属期
                                inInvoice.setDeductiblePeriod(tInDeductionApplyEntry.getDeductiblePeriod());
                                String resultCode = inputDeductionApplyresult.getResultCode();
                                inInvoice.setDeductible(getDeductibleByResultCode(resultCode));
                                inInvoice.setDeductibleName(DictUtils.getDictLabel("", inInvoice.getDeductible()));

                                // 数电发票号码
                                inInvoice.seteInvoiceNumber(inputDeductionApplyresult.getEInvoiceNumber());
                                inInvoice.setUpdateTime(DateUtils.getNowDate());
                                inInvoice.setUpdateBy("勾选抵扣申请结果返回");
                                tInInvoiceMapper.updateTInInvoice(inInvoice);
                            } else {
                                logger.error("发票 {} 认证类型不是抵扣（{} , {}），无法将抵扣结果同步给该发票", inInvoice.getInvoiceNo(), inInvoice.getCertificationType(), inInvoice.getCertificationTypeName());
                            }
                        }
                        tInDeductionApplyService.updateTInDeductionApplyEntry(tInDeductionApplyEntry);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

    /**
     * 2. 请求-取消勾选抵扣
     * @param invoiceIds
     */
    @Override
    public void deductionApplyCancelByInvoiceIds(String[] invoiceIds) {
        // 操作人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        logger.info("用户 {} 操作取消勾选抵扣, 发票集合 {}", loginUser.getUsername(), invoiceIds);
        TSysSite site = tSysSiteService.getCurrentSite();

        // 申请发票数
        Integer applyQty = 0;
        // 申请抵扣金额
        BigDecimal applyAmount = BigDecimal.ZERO;
        // 申请日期
        Date applyTime = DateUtils.getNowDate();
        // 申请人
        String applyBy = loginUser.getUser().getNickName();

        // 请求参数
        List<DeductionApplyInvoice> deductionApplyInvoiceList = new ArrayList<>();
        for(String invoiceId : invoiceIds){
            TInInvoice inInvoice = tInInvoiceMapper.selectTInInvoiceByInvoiceId(invoiceId);
            // 校验
            if(!inInvoice.getIsInvoicedataSync().equals("1")){
                throw new ServiceException("发票 " + inInvoice.getInvoiceNo() + "无法抵扣，请先执行抵扣同步");
            }
            if(inInvoice.getDeductTax() == null){
                throw new ServiceException("发票 " + inInvoice.getInvoiceNo() + "无抵扣金额，无法抵扣");
            }
            if(inInvoice.getCertificationType() == null){
                throw new ServiceException("发票 " + inInvoice.getInvoiceNo() + "无认证类型，无法抵扣");
            }
            DeductionApplyInvoice deductionApplyInvoice = new DeductionApplyInvoice();
            // 认证类型：5-取消抵扣 默认5
            deductionApplyInvoice.setCertificationType(CertificationType.CANCEL_CERTIFICATION.getCode());
            // 抵扣税额
            deductionApplyInvoice.setEffectiveTax(inInvoice.getDeductTax().toString());
            //
            deductionApplyInvoice.setInvoiceNumber(inInvoice.getInvoiceNo());
            //
            deductionApplyInvoice.setInvoiceCode(inInvoice.getInvoiceCode());
            //
            deductionApplyInvoice.setPurchaserTaxNo(inInvoice.getPurchaserTaxNo());
            deductionApplyInvoiceList.add(deductionApplyInvoice);

            applyAmount = applyAmount.add(inInvoice.getDeductTax());
        }
        applyQty = deductionApplyInvoiceList.size();
        String taxNo = site.getTaxNumber();
        String period = DateUtils.getCurrentMonth();

        // 校验通过后，生成一个申请记录
        TInDeductionApply tInDeductionApply = new TInDeductionApply();
        tInDeductionApply.setCustId(site.getCustId());
        tInDeductionApply.setSiteCode(site.getSiteCode());
        tInDeductionApply.setSiteName(site.getSiteName());
        // 取消勾选申请
        tInDeductionApply.setApplyType(ApplyType.APPLY_CANCEL.getCode());
        tInDeductionApply.setApplyTypeName(ApplyType.APPLY_CANCEL.getName());
        // 抵扣
        tInDeductionApply.setApplyCertificationType(CertificationType.CANCEL_CERTIFICATION.getCode());
        tInDeductionApply.setApplyCertificationTypeName(CertificationType.CANCEL_CERTIFICATION.getName());

        tInDeductionApply.setApplyAmount(applyAmount);
        tInDeductionApply.setApplyBy(applyBy);
        tInDeductionApply.setApplyQty(applyQty);
        tInDeductionApply.setTaxNo(taxNo);
        tInDeductionApply.setPeriod(period);
        tInDeductionApply.setSuccess("");
        tInDeductionApply.setCode("");
        tInDeductionApply.setMessage("");
        // 申请记录的明细
        List<TInDeductionApplyEntry> tInDeductionApplyEntryList = new ArrayList<>();
        for(DeductionApplyInvoice deductionApplyInvoice : deductionApplyInvoiceList){
            TInDeductionApplyEntry tInDeductionApplyEntry = new TInDeductionApplyEntry();
            tInDeductionApplyEntry.setCertificationType(CertificationType.CANCEL_CERTIFICATION.getCode());
            tInDeductionApplyEntry.setCertificationTypeName(CertificationType.CANCEL_CERTIFICATION.getName());
            tInDeductionApplyEntry.setTaskNo(taxNo);
            tInDeductionApplyEntry.setPeriod(period);
            tInDeductionApplyEntry.setInvoiceCode(deductionApplyInvoice.getInvoiceCode());
            tInDeductionApplyEntry.setInvoiceNumber(deductionApplyInvoice.getInvoiceNumber());
            tInDeductionApplyEntry.setEinvoiceNumber(deductionApplyInvoice.geteInvoiceNumber());
            tInDeductionApplyEntry.setEffectiveTax(deductionApplyInvoice.getEffectiveTax());
            // 初始化结果业务字段
            tInDeductionApplyEntry.setTaskNo("");
            tInDeductionApplyEntry.setDeductibleDate("");
            tInDeductionApplyEntry.setDeductiblePeriod("");
            tInDeductionApplyEntry.setResultCode("");
            tInDeductionApplyEntry.setResultName("");
            tInDeductionApplyEntryList.add(tInDeductionApplyEntry);
        }
        tInDeductionApply.setTInDeductionApplyEntryList(tInDeductionApplyEntryList);
        if(tInDeductionApplyService.insertTInDeductionApply(tInDeductionApply) == 1){
            // 调用百望取消勾选抵扣申请接口
            InputDeductionCancelResponse inputDeductionCancelResponse = BaiwangUtils.deductionCancel(taxNo, period , deductionApplyInvoiceList);
            // 返回失败
            if(!inputDeductionCancelResponse.getSuccess()){
                logger.error("取消勾选抵扣申请接口异常：" + inputDeductionCancelResponse.getErrorResponse().getMessage());
                // 修改勾选申请记录的结果
                tInDeductionApply.setSuccess("false");
                // 具体的错误码
                ErrorResponse errorResponse = inputDeductionCancelResponse.getErrorResponse();
                tInDeductionApply.setCode(errorResponse.getCode());
                tInDeductionApply.setMessage(errorResponse.getMessage());
                tInDeductionApply.setUpdateBy("接口返回异常");
                tInDeductionApplyService.updateTInDeductionApplyOnly(tInDeductionApply);
            }
            // 返回成功
            else {
                // 修改取消勾选申请记录的结果
                tInDeductionApply.setSuccess("true");
                InputDeductionCancel inputDeductionCancel = inputDeductionCancelResponse.getResponse();
                // 明细
                List<InputDeductionCancelCancelDeductibleResponseInvoice> taskList = inputDeductionCancel.getTaskList();
                for(InputDeductionCancelCancelDeductibleResponseInvoice inputDeductionApplyTask : taskList){
                    for(TInDeductionApplyEntry tInDeductionApplyEntry : tInDeductionApplyEntryList){
                        if(inputDeductionApplyTask.getInvoiceNumber().equals(tInDeductionApplyEntry.getInvoiceNumber())){
                            // 设置任务号
                            tInDeductionApplyEntry.setTaskNo(inputDeductionApplyTask.getTaskNo());
                            // 更新发票认证类型-取消认证
                            TInInvoice inInvoice = selectTInInvoiceByInvoiceNumber(tInDeductionApplyEntry.getInvoiceNumber());
                            if(inInvoice != null){
                                inInvoice.setCertificationType(CertificationType.CANCEL_CERTIFICATION.getCode());
                                inInvoice.setCertificationTypeName(CertificationType.CANCEL_CERTIFICATION.getName());
                                inInvoice.setUpdateBy("取消勾选抵扣申请成功");
                                inInvoice.setUpdateTime(DateUtils.getNowDate());
                                tInInvoiceMapper.updateTInInvoice(inInvoice);
                            }
                        }
                    }
                }
                tInDeductionApply.setTInDeductionApplyEntryList(tInDeductionApplyEntryList);
                if(tInDeductionApplyService.updateTInDeductionApply(tInDeductionApply) == 1) {
                    // 更新成功后，需要查询申请结果
                    ImsAsyncManager.me().execute(ImsAsyncFactory.syncDeductionApplyCancelResultFromBaiwang(tInDeductionApply.getDeductionId()));

                }
            }
        }
    }

    /**
     * 2. 结果-取消勾选抵扣申请结果查询
     * @param deductionId
     */
    @Override
    public void deductionApplyCancelResult(String deductionId) {
        TInDeductionApply tInDeductionApply = tInDeductionApplyService.selectTInDeductionApplyByDeductionId(deductionId);
        logger.info("取消勾选申请 deductionId = {} 准备同步明细的勾选申请结果", deductionId);
        if(tInDeductionApply != null){
            List<TInDeductionApplyEntry> tInDeductionApplyEntryList = tInDeductionApply.getTInDeductionApplyEntryList();
            for(TInDeductionApplyEntry tInDeductionApplyEntry : tInDeductionApplyEntryList){
                InputDeductionCancelresultResponse inputDeductionCancelresultResponse = BaiwangUtils.deductionCancelResult(tInDeductionApplyEntry.getTaxNo(), tInDeductionApplyEntry.getInvoiceCode(), tInDeductionApplyEntry.getInvoiceNumber());
                // 返回失败
                if(!inputDeductionCancelresultResponse.getSuccess()){
                    logger.error("取消勾选抵扣申请结果查询接口异常：" + inputDeductionCancelresultResponse.getErrorResponse().getMessage());
                    tInDeductionApplyEntry.setResultName("取消勾选抵扣申请结果查询接口异常");
                }
                else {
                    InputDeductionCancelresult inputDeductionCancelresult = inputDeductionCancelresultResponse.getResponse();
                    tInDeductionApplyEntry.setDeductiblePeriod("");
                    tInDeductionApplyEntry.setDeductibleDate("");
                    tInDeductionApplyEntry.setResultCode(inputDeductionCancelresult.getResultCode());
                    logger.info(inputDeductionCancelresult.getInvoiceNumber() + "取消抵扣结果：" + DictUtils.getDictLabel("result_code", inputDeductionCancelresult.getResultCode()));
                    tInDeductionApplyEntry.setResultName(DictUtils.getDictLabel("result_code", inputDeductionCancelresult.getResultCode()));
                    logger.info("取消抵扣认证结果：{}" , inputDeductionCancelresult.getDeductibleResultStatus());
                    tInDeductionApplyEntry.setUpdateBy("取消抵扣申请结果返回");
                    try {
                        // 修改对应进项发抵扣状态
                        TInInvoice inInvoice = selectTInInvoiceByInvoiceNumber(tInDeductionApplyEntry.getInvoiceNumber());
                        if(inInvoice == null){
                            logger.error("发票 {} 记录缺失", tInDeductionApplyEntry.getInvoiceNumber());
                        } else {
                            // 发票认证类型必须与接口对齐，即 取消认证
                            if(inInvoice.getCertificationType().equals(CertificationType.CANCEL_CERTIFICATION.getCode())){
                                // 认证结果有直接返回，无需解析处理结果码
                                inInvoice.setDeductible(inputDeductionCancelresult.getDeductibleResultStatus());
                                inInvoice.setDeductibleName(DictUtils.getDictLabel("deductible", inputDeductionCancelresult.getDeductibleResultStatus()));
                                // 若成功取消勾选，则需要删除该票的抵扣税期
                                if(inputDeductionCancelresult.getDeductibleResultStatus().equals(Deductible.WEI_REN_ZHENG.getCode())){
                                    // 认证日期
                                    inInvoice.setDeductibleDate("");
                                    // 税款所属期
                                    inInvoice.setDeductiblePeriod("");
                                } else {
                                    // TODO 未认证则需要隔段时间后继续调用该接口查询结果

                                }
                                inInvoice.setUpdateTime(DateUtils.getNowDate());
                                inInvoice.setUpdateBy("取消勾选抵扣申请结果查询");
                                tInInvoiceMapper.updateTInInvoice(inInvoice);
                            } else {
                                logger.error("发票 {} 认证类型不是取消认证（{} , {}），无法将取消认证结果同步给该发票", inInvoice.getInvoiceNo(), inInvoice.getCertificationType(), inInvoice.getCertificationTypeName());
                            }

                        }
                        tInDeductionApplyService.updateTInDeductionApplyEntry(tInDeductionApplyEntry);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 3. 请求-勾选不抵扣
     * @param invoiceIds
     * @param reason 不抵扣原因
     * @param reasonRemark 不抵扣原因备注
     */
    @Override
    public void deductionCancelnonApplyByInvoiceIds(String[] invoiceIds, String reason, String reasonRemark) {
        if(StringUtils.isEmpty(reason)){
            throw new ServiceException("不抵扣原因不能为空");
        }
        // 操作人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        logger.info("用户 {} 操作勾选不抵扣, 发票集合 {}", loginUser.getUsername(), invoiceIds);
        TSysSite site = tSysSiteService.getCurrentSite();

        // 申请发票数
        Integer applyQty = 0;
        // 申请抵扣金额
        BigDecimal applyAmount = BigDecimal.ZERO;
        // 申请日期
        Date applyTime = DateUtils.getNowDate();
        // 申请人
        String applyBy = loginUser.getUser().getNickName();

        // 请求参数
        List<DeductionApplyorCancelnon> deductionApplyorCancelnonList = new ArrayList<>();
        for(String invoiceId : invoiceIds){
            TInInvoice inInvoice = tInInvoiceMapper.selectTInInvoiceByInvoiceId(invoiceId);
            // 校验
            if(!inInvoice.getIsInvoicedataSync().equals("1")){
                throw new ServiceException("发票 " + inInvoice.getInvoiceNo() + "无法抵扣，请先执行抵扣同步");
            }
            if(inInvoice.getDeductTax() == null){
                throw new ServiceException("发票 " + inInvoice.getInvoiceNo() + "无抵扣金额，无法抵扣");
            }
            if(inInvoice.getCertificationType() == null){
                throw new ServiceException("发票 " + inInvoice.getInvoiceNo() + "无认证类型，无法抵扣");
            }
            DeductionApplyorCancelnon deductionApplyorCancelnon = new DeductionApplyorCancelnon();
            // 不抵扣类型：4-确认不抵扣
            deductionApplyorCancelnon.setCertificationType(CertificationType.NON_DEDUCTION.getCode());
            // 不抵扣原因
            deductionApplyorCancelnon.setReason(reason);
            // 不抵扣原因备注
            deductionApplyorCancelnon.setReasonRemark(reasonRemark);
            //
            deductionApplyorCancelnon.setInvoiceNumber(inInvoice.getInvoiceNo());
            //
            deductionApplyorCancelnon.setInvoiceCode(inInvoice.getInvoiceCode());
            //
            deductionApplyorCancelnon.setPurchaserTaxNo(inInvoice.getPurchaserTaxNo());
            deductionApplyorCancelnonList.add(deductionApplyorCancelnon);

            applyAmount = applyAmount.add(inInvoice.getDeductTax());


        }
        applyQty = deductionApplyorCancelnonList.size();
        String taxNo = site.getTaxNumber();
        String period = DateUtils.getCurrentMonth();

        // 校验通过后，生成一个(不抵扣)申请记录
        TInDeductionApply tInDeductionApply = new TInDeductionApply();
        tInDeductionApply.setCustId(site.getCustId());
        tInDeductionApply.setSiteCode(site.getSiteCode());
        tInDeductionApply.setSiteName(site.getSiteName());
        // 勾选申请
        tInDeductionApply.setApplyType(ApplyType.APPLY.getCode());
        tInDeductionApply.setApplyTypeName(ApplyType.APPLY.getName());
        // 不抵扣
        tInDeductionApply.setApplyCertificationType(CertificationType.NON_DEDUCTION.getCode());
        tInDeductionApply.setApplyCertificationTypeName(CertificationType.NON_DEDUCTION.getName());

        tInDeductionApply.setApplyAmount(applyAmount);
        tInDeductionApply.setApplyBy(applyBy);
        tInDeductionApply.setApplyQty(applyQty);
        tInDeductionApply.setTaxNo(taxNo);
        tInDeductionApply.setPeriod(period);
        tInDeductionApply.setSuccess("");
        tInDeductionApply.setCode("");
        tInDeductionApply.setMessage("");
        // 申请记录的明细
        List<TInDeductionApplyEntry> tInDeductionApplyEntryList = new ArrayList<>();
        for(DeductionApplyorCancelnon deductionApplyorCancelnon : deductionApplyorCancelnonList){
            TInDeductionApplyEntry tInDeductionApplyEntry = new TInDeductionApplyEntry();
            tInDeductionApplyEntry.setCertificationType(CertificationType.NON_DEDUCTION.getCode());
            tInDeductionApplyEntry.setCertificationTypeName(CertificationType.NON_DEDUCTION.getName());
            tInDeductionApplyEntry.setTaskNo(taxNo);
            tInDeductionApplyEntry.setPeriod(period);
            tInDeductionApplyEntry.setInvoiceCode(deductionApplyorCancelnon.getInvoiceCode());
            tInDeductionApplyEntry.setInvoiceNumber(deductionApplyorCancelnon.getInvoiceNumber());
            tInDeductionApplyEntry.setEinvoiceNumber(deductionApplyorCancelnon.geteInvoiceNumber());
            tInDeductionApplyEntry.setEffectiveTax(null);
            // 初始化结果业务字段
            tInDeductionApplyEntry.setTaskNo("");
            tInDeductionApplyEntry.setDeductibleDate("");
            tInDeductionApplyEntry.setDeductiblePeriod("");
            tInDeductionApplyEntry.setResultCode("");
            tInDeductionApplyEntry.setResultName("");
            tInDeductionApplyEntryList.add(tInDeductionApplyEntry);
        }
        tInDeductionApply.setTInDeductionApplyEntryList(tInDeductionApplyEntryList);
        if(tInDeductionApplyService.insertTInDeductionApply(tInDeductionApply) == 1){
            // 调用百望勾选不抵扣申请接口
            InputDeductionApplyorcancelnonResponse inputDeductionApplyorcancelnonResponse = BaiwangUtils.deductionApplyorCancelnon(taxNo, period , deductionApplyorCancelnonList);
            // 返回失败
            if(!inputDeductionApplyorcancelnonResponse.getSuccess()){
                logger.error("勾选不抵扣申请接口异常：" + inputDeductionApplyorcancelnonResponse.getErrorResponse().getMessage());
                // 修改勾选申请记录的结果
                tInDeductionApply.setSuccess("false");
                // 具体的错误码
                ErrorResponse errorResponse = inputDeductionApplyorcancelnonResponse.getErrorResponse();
                tInDeductionApply.setCode(errorResponse.getCode());
                tInDeductionApply.setMessage(errorResponse.getMessage());
                tInDeductionApply.setUpdateBy("接口返回异常");
                tInDeductionApplyService.updateTInDeductionApplyOnly(tInDeductionApply);
            }
            // 返回成功
            else {
                // 修改勾选申请记录的结果
                tInDeductionApply.setSuccess("true");
                InputDeductionApplyorcancelnon inputDeductionApplyorcancelnon = inputDeductionApplyorcancelnonResponse.getResponse();
                // 明细
                List<InputDeductionApplyorcancelnonNoDeductionResponseInvoice> invoiceList = inputDeductionApplyorcancelnon.getInvoiceList();
                for(InputDeductionApplyorcancelnonNoDeductionResponseInvoice invoice : invoiceList){
                    for(TInDeductionApplyEntry tInDeductionApplyEntry : tInDeductionApplyEntryList){
                        if(invoice.getInvoiceNumber().equals(tInDeductionApplyEntry.getInvoiceNumber())){
                            // 设置任务号
                            tInDeductionApplyEntry.setTaskNo(invoice.getTaskNo());
                            // 更新发票认证类型-不抵扣
                            TInInvoice inInvoice = selectTInInvoiceByInvoiceNumber(tInDeductionApplyEntry.getInvoiceNumber());
                            if(inInvoice != null){
                                inInvoice.setCertificationType(CertificationType.NON_DEDUCTION.getCode());
                                inInvoice.setCertificationTypeName(CertificationType.NON_DEDUCTION.getName());
                                inInvoice.setUpdateBy("勾选不抵扣申请成功");
                                inInvoice.setUpdateTime(DateUtils.getNowDate());
                                tInInvoiceMapper.updateTInInvoice(inInvoice);
                            }
                        }
                    }
                }
                tInDeductionApply.setTInDeductionApplyEntryList(tInDeductionApplyEntryList);
                if(tInDeductionApplyService.updateTInDeductionApply(tInDeductionApply) == 1) {
                    // 更新成功后，需要查询申请结果
                    ImsAsyncManager.me().execute(ImsAsyncFactory.syncDeductionCancelnonApplyResultFromBaiwang(tInDeductionApply.getDeductionId()));

                }
            }
        }
    }

    /**
     * 3. 结果-勾选不抵扣申请结果查询
     * @param deductionId
     */
    @Override
    public void deductionCancelnonApplyResult(String deductionId) {
        TInDeductionApply tInDeductionApply = tInDeductionApplyService.selectTInDeductionApplyByDeductionId(deductionId);
        logger.info("勾选申请 deductionId = {} 准备同步明细的勾选（不抵扣）申请结果", deductionId);
        if(tInDeductionApply != null){
            List<TInDeductionApplyEntry> tInDeductionApplyEntryList = tInDeductionApply.getTInDeductionApplyEntryList();
            for(TInDeductionApplyEntry tInDeductionApplyEntry : tInDeductionApplyEntryList){
                InputDeductionApplyorcancelnonresultResponse inputDeductionApplyorcancelnonresultResponse =
                        BaiwangUtils.deductionApplyorCancelnonResult(
                                tInDeductionApplyEntry.getTaxNo(),
                                tInDeductionApplyEntry.getInvoiceCode(),
                                tInDeductionApplyEntry.getInvoiceNumber(),
                                CertificationType.NON_DEDUCTION.getCode(),
                                tInDeductionApplyEntry.getEinvoiceNumber(),
                                tInDeductionApplyEntry.getTaskNo());
                // 返回失败
                if(!inputDeductionApplyorcancelnonresultResponse.getSuccess()){
                    logger.error("勾选不抵扣申请结果查询接口异常：" + inputDeductionApplyorcancelnonresultResponse.getErrorResponse().getMessage());
                    tInDeductionApplyEntry.setResultName("勾选不抵扣申请结果查询接口异常");
                }
                else {
                    InputDeductionApplyorcancelnonresult inputDeductionApplyorcancelnonresult = inputDeductionApplyorcancelnonresultResponse.getResponse();
                    tInDeductionApplyEntry.setResultCode(inputDeductionApplyorcancelnonresult.getResultCode());
                    logger.info(inputDeductionApplyorcancelnonresult.getInvoiceNumber() + "不抵扣结果：" + DictUtils.getDictLabel("result_code", inputDeductionApplyorcancelnonresult.getResultCode()));
                    tInDeductionApplyEntry.setResultName(DictUtils.getDictLabel("result_code", inputDeductionApplyorcancelnonresult.getResultCode()));
                    tInDeductionApplyEntry.setUpdateBy("不抵扣申请结果返回");
                    try {
                        // 修改对应进项发抵扣状态
                        TInInvoice inInvoice = selectTInInvoiceByInvoiceNumber(tInDeductionApplyEntry.getInvoiceNumber());
                        if(inInvoice == null){
                            logger.error("发票 {} 记录缺失", tInDeductionApplyEntry.getInvoiceNumber());
                        } else {
                            // 发票认证类型必须与接口对齐，即 不抵扣
                            if(inInvoice.getCertificationType().equals(CertificationType.NON_DEDUCTION.getCode())){
                                String resultCode = inputDeductionApplyorcancelnonresult.getResultCode();
                                inInvoice.setDeductible(getDeductibleByResultCode(resultCode));
                                inInvoice.setDeductibleName(DictUtils.getDictLabel("", inInvoice.getDeductible()));
                                // 税款所属期
                                inInvoice.setDeductiblePeriod(tInDeductionApplyEntry.getDeductiblePeriod());
                                inInvoice.setUpdateTime(DateUtils.getNowDate());
                                inInvoice.setUpdateBy("勾选不抵扣申请结果查询");
                                tInInvoiceMapper.updateTInInvoice(inInvoice);
                            }  else {
                                logger.error("发票 {} 认证类型不是不抵扣（{} , {}），无法将不抵扣结果同步给该发票", inInvoice.getInvoiceNo(), inInvoice.getCertificationType(), inInvoice.getCertificationTypeName());
                            }
                        }
                        tInDeductionApplyService.updateTInDeductionApplyEntry(tInDeductionApplyEntry);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

    /**
     * 4. 取消勾选不抵扣
     * @param invoiceIds
     * @param reason 不抵扣原因
     * @param reasonRemark 不抵扣原因备注
     */
    @Override
    public void deductionCancelnonApplyCancelByInvoiceIds(String[] invoiceIds, String reason, String reasonRemark) {
        // 操作人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        logger.info("用户 {} 操作取消勾选不抵扣, 发票集合 {}", loginUser.getUsername(), invoiceIds);
        TSysSite site = tSysSiteService.getCurrentSite();

        // 申请发票数
        Integer applyQty = 0;
        // 申请抵扣金额
        BigDecimal applyAmount = BigDecimal.ZERO;
        // 申请日期
        Date applyTime = DateUtils.getNowDate();
        // 申请人
        String applyBy = loginUser.getUser().getNickName();

        // 请求参数
        List<DeductionApplyorCancelnon> deductionApplyorCancelnonList = new ArrayList<>();
        for(String invoiceId : invoiceIds){
            TInInvoice inInvoice = tInInvoiceMapper.selectTInInvoiceByInvoiceId(invoiceId);
            // TODO 校验
            if(!inInvoice.getDeductible().equals(Deductible.REN_ZHENG_TONG_GUO.getCode())){
                throw new ServiceException("发票 " + inInvoice.getInvoiceNo() + "无法不抵扣");
            }
            DeductionApplyorCancelnon deductionApplyorCancelnon = new DeductionApplyorCancelnon();
            // 不抵扣类型：6-取消不抵扣
            deductionApplyorCancelnon.setCertificationType(CertificationType.REVOKE_NON_DEDUCTION.getCode());
            // 不抵扣原因
            deductionApplyorCancelnon.setReason(reason);
            // 不抵扣原因备注
            deductionApplyorCancelnon.setReasonRemark(reasonRemark);
            //
            deductionApplyorCancelnon.setInvoiceNumber(inInvoice.getInvoiceNo());
            //
            deductionApplyorCancelnon.setInvoiceCode(inInvoice.getInvoiceCode());
            //
            deductionApplyorCancelnon.setPurchaserTaxNo(inInvoice.getPurchaserTaxNo());
            deductionApplyorCancelnonList.add(deductionApplyorCancelnon);

            applyAmount = applyAmount.add(inInvoice.getDeductTax());
        }
        applyQty = deductionApplyorCancelnonList.size();
        String taxNo = site.getTaxNumber();
        String period = DateUtils.getCurrentMonth();

        // 校验通过后，生成一个(取消不抵扣)申请记录
        TInDeductionApply tInDeductionApply = new TInDeductionApply();
        tInDeductionApply.setCustId(site.getCustId());
        tInDeductionApply.setSiteCode(site.getSiteCode());
        tInDeductionApply.setSiteName(site.getSiteName());
        // 勾选申请
        tInDeductionApply.setApplyType(ApplyType.APPLY_CANCEL.getCode());
        tInDeductionApply.setApplyTypeName(ApplyType.APPLY_CANCEL.getName());
        // 不抵扣
        tInDeductionApply.setApplyCertificationType(CertificationType.REVOKE_NON_DEDUCTION.getCode());
        tInDeductionApply.setApplyCertificationTypeName(CertificationType.REVOKE_NON_DEDUCTION.getName());

        tInDeductionApply.setApplyAmount(applyAmount);
        tInDeductionApply.setApplyBy(applyBy);
        tInDeductionApply.setApplyQty(applyQty);
        tInDeductionApply.setTaxNo(taxNo);
        tInDeductionApply.setPeriod(period);
        tInDeductionApply.setSuccess("");
        tInDeductionApply.setCode("");
        tInDeductionApply.setMessage("");
        // 申请记录的明细
        List<TInDeductionApplyEntry> tInDeductionApplyEntryList = new ArrayList<>();
        for(DeductionApplyorCancelnon deductionApplyorCancelnon : deductionApplyorCancelnonList){
            TInDeductionApplyEntry tInDeductionApplyEntry = new TInDeductionApplyEntry();
            tInDeductionApplyEntry.setCertificationType(CertificationType.REVOKE_NON_DEDUCTION.getCode());
            tInDeductionApplyEntry.setCertificationTypeName(CertificationType.REVOKE_NON_DEDUCTION.getName());
            tInDeductionApplyEntry.setTaskNo(taxNo);
            tInDeductionApplyEntry.setPeriod(period);
            tInDeductionApplyEntry.setInvoiceCode(deductionApplyorCancelnon.getInvoiceCode());
            tInDeductionApplyEntry.setInvoiceNumber(deductionApplyorCancelnon.getInvoiceNumber());
            tInDeductionApplyEntry.setEinvoiceNumber(deductionApplyorCancelnon.geteInvoiceNumber());
            tInDeductionApplyEntry.setEffectiveTax(null);
            // 初始化结果业务字段
            tInDeductionApplyEntry.setTaskNo("");
            tInDeductionApplyEntry.setDeductibleDate("");
            tInDeductionApplyEntry.setDeductiblePeriod("");
            tInDeductionApplyEntry.setResultCode("");
            tInDeductionApplyEntry.setResultName("");
            tInDeductionApplyEntryList.add(tInDeductionApplyEntry);
        }
        tInDeductionApply.setTInDeductionApplyEntryList(tInDeductionApplyEntryList);
        if(tInDeductionApplyService.insertTInDeductionApply(tInDeductionApply) == 1){
            // 调用百望勾选不抵扣申请接口
            InputDeductionApplyorcancelnonResponse inputDeductionApplyorcancelnonResponse = BaiwangUtils.deductionApplyorCancelnon(taxNo, period , deductionApplyorCancelnonList);
            // 返回失败
            if(!inputDeductionApplyorcancelnonResponse.getSuccess()){
                logger.error("取消勾选不抵扣申请接口异常：" + inputDeductionApplyorcancelnonResponse.getErrorResponse().getMessage());
                // 修改勾选申请记录的结果
                tInDeductionApply.setSuccess("false");
                // 具体的错误码
                ErrorResponse errorResponse = inputDeductionApplyorcancelnonResponse.getErrorResponse();
                tInDeductionApply.setCode(errorResponse.getCode());
                tInDeductionApply.setMessage(errorResponse.getMessage());
                tInDeductionApply.setUpdateBy("接口返回异常");
                tInDeductionApplyService.updateTInDeductionApplyOnly(tInDeductionApply);
            }
            // 返回成功
            else {
                // 修改勾选申请记录的结果
                tInDeductionApply.setSuccess("true");
                InputDeductionApplyorcancelnon inputDeductionApplyorcancelnon = inputDeductionApplyorcancelnonResponse.getResponse();
                // 明细
                List<InputDeductionApplyorcancelnonNoDeductionResponseInvoice> invoiceList = inputDeductionApplyorcancelnon.getInvoiceList();
                for(InputDeductionApplyorcancelnonNoDeductionResponseInvoice invoice : invoiceList){
                    for(TInDeductionApplyEntry tInDeductionApplyEntry : tInDeductionApplyEntryList){
                        if(invoice.getInvoiceNumber().equals(tInDeductionApplyEntry.getInvoiceNumber())){
                            // 设置任务号
                            tInDeductionApplyEntry.setTaskNo(invoice.getTaskNo());
                            // 更新发票认证类型-撤销不抵扣
                            TInInvoice inInvoice = selectTInInvoiceByInvoiceNumber(tInDeductionApplyEntry.getInvoiceNumber());
                            if(inInvoice != null){
                                inInvoice.setCertificationType(CertificationType.REVOKE_NON_DEDUCTION.getCode());
                                inInvoice.setCertificationTypeName(CertificationType.REVOKE_NON_DEDUCTION.getName());
                                inInvoice.setUpdateBy("撤销不抵扣申请成功");
                                inInvoice.setUpdateTime(DateUtils.getNowDate());
                                tInInvoiceMapper.updateTInInvoice(inInvoice);
                            }
                        }
                    }
                }
                tInDeductionApply.setTInDeductionApplyEntryList(tInDeductionApplyEntryList);
                if(tInDeductionApplyService.updateTInDeductionApply(tInDeductionApply) == 1) {
                    // 更新成功后，需要查询申请结果
                    ImsAsyncManager.me().execute(ImsAsyncFactory.syncDeductionCancelnonApplyCancelResultFromBaiwang(tInDeductionApply.getDeductionId()));
                }
            }
        }
    }


    /**
     * 4. 结果-取消勾选不抵扣申请结果查询
     * @param deductionId
     */
    @Override
    public void deductionCancelnonApplyCancelResult(String deductionId) {
        TInDeductionApply tInDeductionApply = tInDeductionApplyService.selectTInDeductionApplyByDeductionId(deductionId);
        logger.info("勾选申请 deductionId = {} 准备同步明细的勾选（取消不抵扣）申请结果", deductionId);
        if(tInDeductionApply != null){
            List<TInDeductionApplyEntry> tInDeductionApplyEntryList = tInDeductionApply.getTInDeductionApplyEntryList();
            for(TInDeductionApplyEntry tInDeductionApplyEntry : tInDeductionApplyEntryList){
                InputDeductionApplyorcancelnonresultResponse inputDeductionApplyorcancelnonresultResponse =
                        BaiwangUtils.deductionApplyorCancelnonResult(
                                tInDeductionApplyEntry.getTaxNo(),
                                tInDeductionApplyEntry.getInvoiceCode(),
                                tInDeductionApplyEntry.getInvoiceNumber(),
                                CertificationType.REVOKE_NON_DEDUCTION.getCode(),
                                tInDeductionApplyEntry.getEinvoiceNumber(),
                                tInDeductionApplyEntry.getTaskNo());
                // 返回失败
                if(!inputDeductionApplyorcancelnonresultResponse.getSuccess()){
                    logger.error("取消不抵扣申请结果查询接口异常：" + inputDeductionApplyorcancelnonresultResponse.getErrorResponse().getMessage());
                    tInDeductionApplyEntry.setResultName("取消不抵扣申请结果查询接口异常");
                }
                else {
                    InputDeductionApplyorcancelnonresult inputDeductionApplyorcancelnonresult = inputDeductionApplyorcancelnonresultResponse.getResponse();
                    tInDeductionApplyEntry.setResultCode(inputDeductionApplyorcancelnonresult.getResultCode());
                    logger.info(inputDeductionApplyorcancelnonresult.getInvoiceNumber() + "不抵扣结果：" + DictUtils.getDictLabel("result_code", inputDeductionApplyorcancelnonresult.getResultCode()));
                    tInDeductionApplyEntry.setResultName(DictUtils.getDictLabel("result_code", inputDeductionApplyorcancelnonresult.getResultCode()));
                    tInDeductionApplyEntry.setUpdateBy("不抵扣申请结果返回");
                    try {
                        // 修改对应进项发抵扣状态
                        TInInvoice inInvoice = selectTInInvoiceByInvoiceNumber(tInDeductionApplyEntry.getInvoiceNumber());
                        if(inInvoice == null){
                            logger.error("发票 {} 记录缺失", tInDeductionApplyEntry.getInvoiceNumber());
                        } else {
                            // 发票认证类型必须与接口对齐，即 撤销不抵扣
                            if(inInvoice.getCertificationType().equals(CertificationType.REVOKE_NON_DEDUCTION.getCode())){
                                String resultCode = inputDeductionApplyorcancelnonresult.getResultCode();
                                inInvoice.setDeductible(getDeductibleByResultCode(resultCode));
                                inInvoice.setDeductibleName(DictUtils.getDictLabel("", inInvoice.getDeductible()));
                                // 若通过认证，则表示发票已撤销不抵扣，需将发票税款所属期清除
                                if(inInvoice.getDeductible().equals(Deductible.REN_ZHENG_TONG_GUO.getCode())){
                                    // 税款所属期
                                    inInvoice.setDeductiblePeriod("");
                                    inInvoice.setUpdateTime(DateUtils.getNowDate());
                                } else {
                                    // 若没通过认证，则不需要修改
                                }
                                inInvoice.setUpdateBy("勾选不抵扣申请结果查询");
                                tInInvoiceMapper.updateTInInvoice(inInvoice);
                            }  else {
                                logger.error("发票 {} 认证类型不是撤销不抵扣（{} , {}），无法将撤销不抵扣结果同步给该发票", inInvoice.getInvoiceNo(), inInvoice.getCertificationType(), inInvoice.getCertificationTypeName());
                            }
                        }
                        tInDeductionApplyService.updateTInDeductionApplyEntry(tInDeductionApplyEntry);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }


    /**
     * 根据结果码生成认证结果
     * @param resultCode
     * @return
     */
    private String getDeductibleByResultCode(String resultCode){
        // 认证结果
        if(
            // 1：认证成功
            resultCode.equals(ResultCode.AUTHENTICATION_SUCCESS.getCode())
            //4：该票已经认证
            || resultCode.equals(ResultCode.INVOICE_ALREADY_AUTHENTICATED.getCode())
        ){
            return Deductible.REN_ZHENG_TONG_GUO.getCode();
        }
        else if(
            //0：任务执行中
            resultCode.equals(ResultCode.TASK_EXECUTING.getCode())
        ){
            return Deductible.REN_ZHENG_ZHONG.getCode();
        }
        else if(
            //2：未获取到本发票或本发票之前已勾选
            resultCode.equals(ResultCode.INVOICE_NOT_FOUND_OR_ALREADY_CHECKED.getCode())
            //8：其它异常
            || resultCode.equals(ResultCode.OTHER_ABNORMALITIES.getCode())
            //6：该票已经申请认证
            || resultCode.equals(ResultCode.INVOICE_ALREADY_APPLIED_AUTHENTICATION.getCode())
            //9：发票未到期(需切换税期)
            || resultCode.equals(ResultCode.INVOICE_NOT_DUE_NEED_TAX_PERIOD_SWITCH.getCode())
            //13：未到申报期
            || resultCode.equals(ResultCode.NOT_YET_DECLARATION_PERIOD.getCode())
            //14：该发票税号不匹配
            || resultCode.equals(ResultCode.INVOICE_TAX_NUMBER_MISMATCH.getCode())
            //16：认证类型错误
            || resultCode.equals(ResultCode.AUTHENTICATION_TYPE_ERROR.getCode())
            //17：信用等级异常或无权限
            || resultCode.equals(ResultCode.CREDIT_RATING_ABNORMAL_OR_NO_PERMISSION.getCode())
            //18：登陆税局失败
            || resultCode.equals(ResultCode.LOGIN_TAX_BUREAU_FAILED.getCode())
            //20：有效税额异常(有效税额大于实际税额)
            || resultCode.equals(ResultCode.EFFECTIVE_TAX_AMOUNT_ABNORMAL.getCode())
            //21：当期已锁定
            || resultCode.equals(ResultCode.CURRENT_PERIOD_LOCKED.getCode())
            //23：发票未勾选（确认）
            || resultCode.equals(ResultCode.INVOICE_NOT_CHECKED_CONFIRMED.getCode())
            //24：取消操作不匹配
            || resultCode.equals(ResultCode.CANCEL_OPERATION_MISMATCH.getCode())
            //41：需等待上次申请完成
            || resultCode.equals(ResultCode.WAIT_FOR_PREVIOUS_APPLICATION_COMPLETE.getCode())
            //42：勾选时间范围有误
            || resultCode.equals(ResultCode.ERROR_TIME_FRAME.getCode())
            //52：该票已勾选的税期和当前税期不一致
            || resultCode.equals(ResultCode.INVOICE_CHECKED_TAX_PERIOD_MISMATCH.getCode())
        ){
            return Deductible.WEI_REN_ZHENG.getCode();
        } else {
            return Deductible.REN_ZHENG_BU_TONG_GUO.getCode();
        }
    }
}
